Home of the original IBM PC emulator for browsers.
The following document is from the Microsoft Programmer’s Library 1.3 CD-ROM.
Microsoft Windows S.D.K. v3.0 Sample `C' Source Code
BITMAP.C
CD-ROM Disc Path: \SAMPCODE\WIN_SDK\BITMAP\BITMAP.C
/****************************************************************************
PROGRAM: Bitmap.c
PURPOSE: Demonstrates how to use bitmap
FUNCTIONS:
WinMain() - calls initialization function, processes message loop
InitApplication() - initializes window data and registers window
InitInstance() - saves instance handle and creates main window
MainWndProc() - processes messages
About() - processes messages for "About" dialog box
MakeColorBitmap(HWND) - creates a color bitmap
COMMENTS:
This application is linked with select.exe which is a library
module. For the source code, look in the \select\ directory, and
in Appendix C of the Windows Programmer's Learning Guide.
****************************************************************************/
#include "windows.h"
#include "bitmap.h"
"select.h" /* used to link with select.exe */
HANDLE hInst;
/* Patterns used for the background */
short White[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
short Black[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
short Zigzag[] = { 0xFF, 0xF7, 0xEB, 0xDD, 0xBE, 0x7F, 0xFF, 0xFF };
short CrossHatch[] = { 0xEF, 0xEF, 0xEF, 0xEF, 0x00, 0xEF, 0xEF, 0xEF };
/* handles used for the various bitmaps */
HBITMAP hPattern1;
HBITMAP hPattern2;
HBITMAP hPattern3;
HBITMAP hPattern4;
HBITMAP hBitmap1;
HBITMAP hBitmap2;
HBITMAP hBitmap3;
HBITMAP hMenuBitmap1;
HBITMAP hMenuBitmap2;
HBITMAP hMenuBitmap3;
HBITMAP hBitmap;
HBITMAP hOldBitmap;
HBRUSH hBrush; /* brush handle
int fStretchMode; /* type of stretch mode to use
HDC hDC; /* handle to device context
HDC hMemoryDC; /* handle to memory device context
BITMAP Bitmap; /* bitmap structure
BOOL bTrack = FALSE; /* TRUE if user is selecting a region
RECT Rect;
/* The following variables keep track of which menu item is checked */
WORD wPrevBitmap = IDM_BITMAP1;
WORD wPrevPattern = IDM_PATTERN1;
WORD wPrevMode = IDM_WHITEONBLACK;
WORD wPrevItem;
int Shape = SL_BLOCK; /* shape to use for the selection rectangle
/****************************************************************************
FUNCTION: WinMain(HANDLE, HANDLE, LPSTR, int)
PURPOSE: calls initialization function, processes message loop
****************************************************************************/
int PASCAL WinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow)
HANDLE hInstance;
HANDLE hPrevInstance;
LPSTR lpCmdLine;
int nCmdShow;
{
MSG msg;
if (!hPrevInstance)
if (!InitApplication(hInstance))
return (FALSE);
if (!InitInstance(hInstance, nCmdShow))
return (FALSE);
while (GetMessage(&msg, NULL, NULL, NULL)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (msg.wParam);
}
/****************************************************************************
FUNCTION: InitApplication(HANDLE)
PURPOSE: Initializes window data and registers window class
****************************************************************************/
BOOL InitApplication(hInstance)
HANDLE hInstance;
{
WNDCLASS wc;
wc.style = CS_VREDRAW | CS_HREDRAW;
wc.lpfnWndProc = MainWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = "BitmapMenu";
wc.lpszClassName = "BitmapWClass";
return (RegisterClass(&wc));
}
/****************************************************************************
FUNCTION: InitInstance(HANDLE, int)
PURPOSE: Saves instance handle and creates main window
****************************************************************************/
BOOL InitInstance(hInstance, nCmdShow)
HANDLE hInstance;
int nCmdShow;
{
HWND hwnd;
hInst = hInstance;
hwnd = CreateWindow(
"BitmapWClass",
"Bitmap Sample Application",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
hInstance,
NULL
);
if (!hwnd)
return (FALSE);
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
return (TRUE);
}
/****************************************************************************
FUNCTION: MainWndProc(HWND, unsigned, WORD, LONG)
PURPOSE: Processes messages
MESSAGES:
WM_COMMAND - application menu (About dialog box)
WM_CREATE - create window and objects
WM_LBUTTONDOWN - begin selection
WM_MOUSEMOVE - keep track of mouse movement during selection
WM_LBUTTONUP - end selection, draw bitmap
WM_RBUTTONUP - draw bitmap without resizing
WM_ERASEBKGND - erase background and redraw
WM_DESTROY - destroy window
COMMENTS:
User may select a "normal" size bitmap by pressing the right mouse
button, or set the size of the bitmap to display by using the left
button to define a region. The routines to display the selection
region are defined in the library module select.exe.
WM_DESTROY - destroy window
****************************************************************************/
long FAR PASCAL MainWndProc(hWnd, message, wParam, lParam)
HWND hWnd;
unsigned message;
WORD wParam;
LONG lParam;
{
FARPROC lpProcAbout;
HMENU hMenu;
HBRUSH hOldBrush;
HBITMAP hOurBitmap;
switch (message) {
case WM_CREATE: /* message: create window
hPattern1 = CreateBitmap(8, 8, 1, 1, (LPSTR) White);
hPattern2 = CreateBitmap(8, 8, 1, 1, (LPSTR) Black);
hPattern3 = CreateBitmap(8, 8, 1, 1, (LPSTR) Zigzag);
hPattern4 = CreateBitmap(8, 8, 1, 1, (LPSTR) CrossHatch);
hBitmap1 = LoadBitmap(hInst, "dog");
hBitmap2 = LoadBitmap(hInst, "cat");
hBitmap3 = MakeColorBitmap(hWnd);
hMenuBitmap1 = LoadBitmap(hInst, "dog");
hMenuBitmap2 = LoadBitmap(hInst, "cat");
hMenuBitmap3 = MakeColorBitmap(hWnd);
hMenu = CreateMenu();
AppendMenu(hMenu, MF_STRING | MF_CHECKED, IDM_PATTERN1, "&White");
AppendMenu(hMenu, MF_STRING, IDM_PATTERN2, "&Black");
AppendMenu(hMenu, MF_BITMAP, IDM_PATTERN3,
(LPSTR)(LONG)hPattern3);
AppendMenu(hMenu, MF_BITMAP, IDM_PATTERN4,
(LPSTR)(LONG)hPattern4);
ModifyMenu(GetMenu(hWnd), 1, MF_POPUP | MF_BYPOSITION,
(WORD)hMenu, "&Pattern");
hMenu = CreateMenu();
/* Use bitmaps for menu items */
AppendMenu(hMenu, MF_BITMAP | MF_CHECKED, IDM_BITMAP1,
(LPSTR)(LONG) hMenuBitmap1);
AppendMenu(hMenu, MF_BITMAP, IDM_BITMAP2,
(LPSTR)(LONG) hMenuBitmap2);
AppendMenu(hMenu, MF_BITMAP, IDM_BITMAP3,
(LPSTR)(LONG) hMenuBitmap3);
ModifyMenu(GetMenu(hWnd), 0, MF_POPUP | MF_BYPOSITION,
(WORD) hMenu, "&Bitmap");
hBrush = CreatePatternBrush(hPattern1);
fStretchMode = IDM_BLACKONWHITE;
/* Select the first bitmap */
hDC = GetDC(hWnd);
hMemoryDC = CreateCompatibleDC(hDC);
ReleaseDC(hWnd, hDC);
hOldBitmap = SelectObject(hMemoryDC, hBitmap1);
GetObject(hBitmap1, 16, (LPSTR) &Bitmap);
break;
case WM_LBUTTONDOWN: /* message: left mouse button pressed
/* Start selection of region */
bTrack = TRUE;
SetRectEmpty(&Rect);
StartSelection(hWnd, MAKEPOINT(lParam), &Rect,
(wParam & MK_SHIFT) ? (SL_EXTEND | Shape) : Shape);
break;
case WM_MOUSEMOVE: /* message: mouse movement
/* Update the selection region */
if (bTrack)
UpdateSelection(hWnd, MAKEPOINT(lParam), &Rect, Shape);
break;
case WM_LBUTTONUP: /* message: left mouse button released
if (bTrack) {
/* End the selection */
EndSelection(MAKEPOINT(lParam), &Rect);
ClearSelection(hWnd, &Rect, Shape);
hDC = GetDC(hWnd);
SetStretchBltMode(hDC, fStretchMode);
StretchBlt(hDC, Rect.left, Rect.top,
Rect.right - Rect.left, Rect.bottom - Rect.top,
hMemoryDC, 0, 0, Bitmap.bmWidth, Bitmap.bmHeight, SRCCOPY);
ReleaseDC(hWnd, hDC);
}
bTrack = FALSE;
break;
case WM_RBUTTONUP: /* message: right mouse button released
/* Display a normal sized bitmap */
hDC = GetDC(hWnd);
BitBlt(hDC, LOWORD(lParam), HIWORD(lParam),
Bitmap.bmWidth, Bitmap.bmHeight, hMemoryDC, 0, 0, SRCCOPY);
ReleaseDC(hWnd, hDC);
break;
case WM_ERASEBKGND: /* messsage: erase background
/* Repaint the background */
UnrealizeObject(hBrush);
hOldBrush = SelectObject(wParam, hBrush);
GetClientRect(hWnd, &Rect);
PatBlt(wParam, Rect.left, Rect.top,
Rect.right-Rect.left, Rect.bottom-Rect.top, PATCOPY);
SelectObject(wParam, hOldBrush);
return TRUE;
case WM_COMMAND:
switch (wParam) {
case IDM_ABOUT:
lpProcAbout = MakeProcInstance(About, hInst);
DialogBox(hInst,
"AboutBox",
hWnd,
lpProcAbout);
FreeProcInstance(lpProcAbout);
break;
case IDM_BITMAP1:
wPrevItem = wPrevBitmap;
wPrevBitmap = wParam;
GetObject(hBitmap1, 16, (LPSTR) &Bitmap);
SelectObject(hMemoryDC, hBitmap1);
break;
case IDM_BITMAP2:
wPrevItem = wPrevBitmap;
wPrevBitmap = wParam;
GetObject(hBitmap2, 16, (LPSTR) &Bitmap);
SelectObject(hMemoryDC, hBitmap2);
break;
case IDM_BITMAP3:
wPrevItem = wPrevBitmap;
wPrevBitmap = wParam;
GetObject(hBitmap3, 16, (LPSTR) &Bitmap);
hOurBitmap = SelectObject(hMemoryDC, hBitmap3);
break;
/* Pattern menu: select the background brush to use */
case IDM_PATTERN1:
wPrevItem = wPrevPattern;
wPrevPattern = wParam;
DeleteObject(hBrush);
hBrush = CreatePatternBrush(hPattern1);
InvalidateRect(hWnd, (LPRECT) NULL, TRUE);
UpdateWindow(hWnd);
break;
case IDM_PATTERN2:
wPrevItem = wPrevPattern;
wPrevPattern = wParam;
DeleteObject(hBrush);
hBrush = CreatePatternBrush(hPattern2);
InvalidateRect(hWnd, (LPRECT) NULL, TRUE);
UpdateWindow(hWnd);
break;
case IDM_PATTERN3:
wPrevItem = wPrevPattern;
wPrevPattern = wParam;
DeleteObject(hBrush);
hBrush = CreatePatternBrush(hPattern3);
InvalidateRect(hWnd, (LPRECT) NULL, TRUE);
UpdateWindow(hWnd);
break;
case IDM_PATTERN4:
wPrevItem = wPrevPattern;
wPrevPattern = wParam;
DeleteObject(hBrush);
hBrush = CreatePatternBrush(hPattern4);
InvalidateRect(hWnd, (LPRECT) NULL, TRUE);
UpdateWindow(hWnd);
break;
/* Mode menu: select the stretch mode to use */
case IDM_BLACKONWHITE:
wPrevItem = wPrevMode;
wPrevMode = wParam;
fStretchMode = BLACKONWHITE;
break;
case IDM_WHITEONBLACK:
wPrevItem = wPrevMode;
wPrevMode = wParam;
fStretchMode = WHITEONBLACK;
break;
case IDM_COLORONCOLOR:
wPrevItem = wPrevMode;
wPrevMode = wParam;
fStretchMode = COLORONCOLOR;
break;
}
/* Uncheck the old item, check the new item */
CheckMenuItem(GetMenu(hWnd), wPrevItem, MF_UNCHECKED);
CheckMenuItem(GetMenu(hWnd), wParam, MF_CHECKED);
break;
case WM_DESTROY:
SelectObject(hMemoryDC, hOldBitmap);
DeleteDC(hMemoryDC);
DeleteObject(hBrush);
DeleteObject(hPattern1);
DeleteObject(hPattern2);
DeleteObject(hPattern3);
DeleteObject(hPattern4);
DeleteObject(hBitmap1);
DeleteObject(hBitmap2);
DeleteObject(hBitmap3);
DeleteObject(hMenuBitmap1);
DeleteObject(hMenuBitmap2);
DeleteObject(hMenuBitmap3);
PostQuitMessage(0);
break;
default:
return (DefWindowProc(hWnd, message, wParam, lParam));
}
return (NULL);
}
/****************************************************************************
FUNCTION: About(HWND, unsigned, WORD, LONG)
PURPOSE: Processes messages for "About" dialog box
MESSAGES:
WM_INITDIALOG - initialize dialog box
WM_COMMAND - Input received
****************************************************************************/
BOOL FAR PASCAL About(hDlg, message, wParam, lParam)
HWND hDlg;
unsigned message;
WORD wParam;
LONG lParam;
{
switch (message) {
case WM_INITDIALOG:
return (TRUE);
case WM_COMMAND:
if (wParam == IDOK
|| wParam == IDCANCEL) {
EndDialog(hDlg, TRUE);
return (TRUE);
}
break;
}
return (FALSE);
}
/****************************************************************************
FUNCTION: MakeColorBitmap(HWND)
PURPOSE: Creates a color bitmap
COMMENTS:
This creates a plaid color bitmap by using overlappying colors.
****************************************************************************/
HBITMAP MakeColorBitmap(hWnd)
HWND hWnd;
{
HDC hDC;
HDC hMemoryDC;
HBITMAP hBitmap;
HBITMAP hOldBitmap;
HBRUSH hRedBrush;
HBRUSH hGreenBrush;
HBRUSH hBlueBrush;
HBRUSH hOldBrush;
hDC = GetDC(hWnd);
hMemoryDC = CreateCompatibleDC(hDC);
hBitmap = CreateCompatibleBitmap(hDC, 64, 32);
hOldBitmap = SelectObject(hMemoryDC, hBitmap);
hRedBrush = CreateSolidBrush(RGB(255,0,0));
hGreenBrush = CreateSolidBrush(RGB(0,255,0));
hBlueBrush = CreateSolidBrush(RGB(0,0,255));
PatBlt(hMemoryDC, 0, 0, 64, 32, BLACKNESS);
hOldBrush = SelectObject(hMemoryDC, hRedBrush);
PatBlt(hMemoryDC, 0, 0, 24, 11, PATORDEST);
PatBlt(hMemoryDC, 40, 10, 24, 12, PATORDEST);
PatBlt(hMemoryDC, 20, 21, 24, 11, PATORDEST);
SelectObject(hMemoryDC, hGreenBrush);
PatBlt(hMemoryDC, 20, 0, 24, 11, PATORDEST);
PatBlt(hMemoryDC, 0, 10, 24, 12, PATORDEST);
PatBlt(hMemoryDC, 40, 21, 24, 11, PATORDEST);
SelectObject(hMemoryDC, hBlueBrush);
PatBlt(hMemoryDC, 40, 0, 24, 11, PATORDEST);
PatBlt(hMemoryDC, 20, 10, 24, 12, PATORDEST);
PatBlt(hMemoryDC, 0, 21, 24, 11, PATORDEST);
SelectObject(hMemoryDC, hOldBrush);
DeleteObject(hRedBrush);
DeleteObject(hGreenBrush);
DeleteObject(hBlueBrush);
SelectObject(hMemoryDC, hOldBitmap);
DeleteDC(hMemoryDC);
ReleaseDC(hWnd, hDC);
return (hBitmap);
}
CFONT.C
CD-ROM Disc Path: \SAMPCODE\WIN_SDK\SHOWFONT\CFONT.C
/****************************************************************************
MODULE: cfont.c
FUNCTION: CFontDlg(HWND, unsigned, WORD, LONG);
PURPOSE: Processes dialog box messages for creating a font
****************************************************************************/
#include "windows.h"
#include "showfont.h"
BOOL FAR PASCAL CFontDlg(hDlg, message, wParam, lParam)
HWND hDlg;
unsigned message;
WORD wParam;
LONG lParam;
{
switch (message) {
case WM_INITDIALOG:
SetDlgItemInt(hDlg, ID_HEIGHT, CLogFont.lfHeight, TRUE);
SetDlgItemInt(hDlg, ID_WIDTH, CLogFont.lfWidth, TRUE);
SetDlgItemInt(hDlg, ID_ESCAPEMENT,
CLogFont.lfEscapement, TRUE);
SetDlgItemInt(hDlg, ID_ORIENTATION,
CLogFont.lfOrientation, TRUE);
SetDlgItemText(hDlg, ID_FACE, CLogFont.lfFaceName);
CheckDlgButton(hDlg, ID_ITALIC, CLogFont.lfItalic);
CheckDlgButton(hDlg, ID_UNDERLINE, CLogFont.lfUnderline);
CheckDlgButton(hDlg, ID_STRIKEOUT, CLogFont.lfStrikeOut);
SetDlgItemInt(hDlg, ID_WEIGHT, CLogFont.lfWeight, TRUE);
switch (CLogFont.lfWeight) {
case FW_LIGHT:
CheckRadioButton(hDlg, ID_LIGHT, ID_BOLD, ID_LIGHT);
break;
case FW_NORMAL:
CheckRadioButton(hDlg, ID_LIGHT, ID_BOLD, ID_NORMAL);
break;
case FW_BOLD:
CheckRadioButton(hDlg, ID_LIGHT, ID_BOLD, ID_BOLD);
break;
}
SetDlgItemInt(hDlg, ID_CHARSET, CLogFont.lfCharSet, TRUE);
switch (CLogFont.lfCharSet) {
case ANSI_CHARSET:
CheckRadioButton(hDlg, ID_ANSI, ID_OEM, ID_ANSI);
break;
case OEM_CHARSET:
CheckRadioButton(hDlg, ID_ANSI, ID_OEM, ID_OEM);
break;
}
switch (CLogFont.lfOutPrecision) {
case OUT_STRING_PRECIS:
CheckRadioButton(hDlg, ID_OUT_STRING, ID_OUT_DEFAULT,
ID_OUT_STRING);
break;
case OUT_CHARACTER_PRECIS:
CheckRadioButton(hDlg, ID_OUT_STRING, ID_OUT_DEFAULT,
ID_OUT_CHAR);
break;
case OUT_STROKE_PRECIS:
CheckRadioButton(hDlg, ID_OUT_STRING, ID_OUT_DEFAULT,
ID_OUT_STROKE);
break;
case OUT_DEFAULT_PRECIS:
CheckRadioButton(hDlg, ID_OUT_STRING, ID_OUT_DEFAULT,
ID_OUT_DEFAULT);
break;
}
switch (CLogFont.lfClipPrecision) {
case CLIP_CHARACTER_PRECIS:
CheckRadioButton(hDlg, ID_CLIP_CHAR, ID_CLIP_DEFAULT,
ID_CLIP_CHAR);
break;
case CLIP_STROKE_PRECIS:
CheckRadioButton(hDlg, ID_CLIP_CHAR, ID_CLIP_DEFAULT,
ID_CLIP_STROKE);
break;
case CLIP_DEFAULT_PRECIS:
CheckRadioButton(hDlg, ID_CLIP_CHAR, ID_CLIP_DEFAULT,
ID_CLIP_DEFAULT);
break;
}
switch (CLogFont.lfQuality) {
case PROOF_QUALITY:
CheckRadioButton(hDlg, ID_PROOF, ID_DEF_QUALITY, ID_PROOF);
break;
case DRAFT_QUALITY:
CheckRadioButton(hDlg, ID_PROOF, ID_DEF_QUALITY, ID_DRAFT);
break;
case DEFAULT_QUALITY:
CheckRadioButton(hDlg, ID_PROOF, ID_DEF_QUALITY,
ID_DEF_QUALITY);
break;
}
switch ((CLogFont.lfPitchAndFamily) & 3) {
case FIXED_PITCH:
CheckRadioButton(hDlg, ID_FIXED, ID_DEF_PITCH, ID_FIXED);
break;
case VARIABLE_PITCH:
CheckRadioButton(hDlg, ID_FIXED, ID_DEF_PITCH, ID_VARIABLE);
break;
case DEFAULT_PITCH:
CheckRadioButton(hDlg, ID_FIXED, ID_DEF_PITCH,
ID_DEF_PITCH);
break;
}
switch ((CLogFont.lfPitchAndFamily) & 240) {
case FF_ROMAN:
CheckRadioButton(hDlg, ID_ROMAN, ID_DEF_FAMILY, ID_ROMAN);
break;
case FF_SWISS:
CheckRadioButton(hDlg, ID_ROMAN, ID_DEF_FAMILY, ID_SWISS);
break;
case FF_MODERN:
CheckRadioButton(hDlg, ID_ROMAN, ID_DEF_FAMILY, ID_MODERN);
break;
case FF_SCRIPT:
CheckRadioButton(hDlg, ID_ROMAN, ID_DEF_FAMILY, ID_SCRIPT);
break;
case FF_DECORATIVE:
CheckRadioButton(hDlg, ID_ROMAN, ID_DEF_FAMILY, ID_DECO);
break;
case FF_DONTCARE:
CheckRadioButton(hDlg, ID_ROMAN, ID_DEF_FAMILY,
ID_DEF_FAMILY);
break;
}
break;
case WM_COMMAND:
switch (wParam) {
case IDOK:
CLogFont.lfHeight = GetDlgItemInt(hDlg,
ID_HEIGHT, NULL, TRUE);
CLogFont.lfWidth = GetDlgItemInt(hDlg,
ID_WIDTH, NULL, TRUE);
CLogFont.lfEscapement = GetDlgItemInt(hDlg,
ID_ESCAPEMENT, NULL, FALSE);
CLogFont.lfOrientation = GetDlgItemInt(hDlg,
ID_ORIENTATION, NULL, FALSE);
GetDlgItemText(hDlg, ID_FACE, CLogFont.lfFaceName, 32);
CLogFont.lfWeight = GetDlgItemInt(hDlg,
ID_WEIGHT, NULL, FALSE);
CLogFont.lfCharSet = GetDlgItemInt(hDlg,
ID_CHARSET, NULL, FALSE);
EndDialog(hDlg, 1);
break;
case IDCANCEL:
EndDialog(hDlg, 0);
break;
case ID_ITALIC:
CLogFont.lfItalic = IsDlgButtonChecked(hDlg, ID_ITALIC);
break;
case ID_UNDERLINE:
CLogFont.lfUnderline = IsDlgButtonChecked(hDlg,
ID_UNDERLINE);
break;
case ID_STRIKEOUT:
CLogFont.lfStrikeOut = IsDlgButtonChecked(hDlg,
ID_STRIKEOUT);
break;
case ID_LIGHT:
SetDlgItemInt(hDlg, ID_WEIGHT, CLogFont.lfWeight, TRUE);
CheckRadioButton(hDlg, ID_LIGHT, ID_BOLD, ID_LIGHT);
CLogFont.lfWeight = FW_LIGHT;
break;
case ID_NORMAL:
SetDlgItemInt(hDlg, ID_WEIGHT, CLogFont.lfWeight, TRUE);
CheckRadioButton(hDlg, ID_LIGHT, ID_BOLD, ID_NORMAL);
CLogFont.lfWeight = FW_NORMAL;
break;
case ID_BOLD:
SetDlgItemInt(hDlg, ID_WEIGHT, CLogFont.lfWeight, TRUE);
CheckRadioButton(hDlg, ID_LIGHT, ID_BOLD, ID_BOLD);
CLogFont.lfWeight = FW_BOLD;
break;
case ID_WEIGHT:
CheckDlgButton(hDlg, ID_LIGHT, FALSE);
CheckDlgButton(hDlg, ID_NORMAL, FALSE);
CheckDlgButton(hDlg, ID_BOLD, FALSE);
break;
case ID_ANSI:
SetDlgItemInt(hDlg, ID_CHARSET, CLogFont.lfCharSet, TRUE);
CheckRadioButton(hDlg, ID_ANSI, ID_OEM, ID_ANSI);
break;
case ID_OEM:
SetDlgItemInt(hDlg, ID_CHARSET, CLogFont.lfCharSet, TRUE);
CheckRadioButton(hDlg, ID_ANSI, ID_OEM, ID_OEM);
break;
case ID_CHARSET:
CheckDlgButton(hDlg, ID_ANSI, FALSE);
CheckDlgButton(hDlg, ID_OEM, FALSE);
break;
case ID_OUT_STRING:
CheckRadioButton(hDlg, ID_OUT_STRING, ID_OUT_DEFAULT,
ID_OUT_STRING);
CLogFont.lfOutPrecision = OUT_STRING_PRECIS;
break;
case ID_OUT_CHAR:
CheckRadioButton(hDlg, ID_OUT_STRING, ID_OUT_DEFAULT,
ID_OUT_CHAR);
CLogFont.lfOutPrecision = OUT_CHARACTER_PRECIS;
break;
case ID_OUT_STROKE:
CheckRadioButton(hDlg, ID_OUT_STRING, ID_OUT_DEFAULT,
ID_OUT_STROKE);
CLogFont.lfOutPrecision = OUT_STROKE_PRECIS;
break;
case ID_OUT_DEFAULT:
CheckRadioButton(hDlg, ID_OUT_STRING, ID_OUT_DEFAULT,
ID_OUT_DEFAULT);
CLogFont.lfOutPrecision = OUT_DEFAULT_PRECIS;
break;
case ID_CLIP_CHAR:
CheckRadioButton(hDlg, ID_CLIP_CHAR, ID_CLIP_DEFAULT,
ID_CLIP_CHAR);
CLogFont.lfClipPrecision = CLIP_CHARACTER_PRECIS;
break;
case ID_CLIP_STROKE:
CheckRadioButton(hDlg, ID_CLIP_CHAR, ID_CLIP_DEFAULT,
ID_CLIP_STROKE);
CLogFont.lfClipPrecision = CLIP_STROKE_PRECIS;
break;
case ID_CLIP_DEFAULT:
CheckRadioButton(hDlg, ID_CLIP_CHAR, ID_CLIP_DEFAULT,
ID_CLIP_DEFAULT);
CLogFont.lfClipPrecision = CLIP_DEFAULT_PRECIS;
break;
case ID_PROOF:
CheckRadioButton(hDlg, ID_PROOF, ID_DEF_QUALITY, ID_PROOF);
CLogFont.lfQuality = PROOF_QUALITY;
break;
case ID_DRAFT:
CheckRadioButton(hDlg, ID_PROOF, ID_DEF_QUALITY, ID_DRAFT);
CLogFont.lfQuality = DRAFT_QUALITY;
break;
case ID_DEF_QUALITY:
CheckRadioButton(hDlg, ID_PROOF, ID_DEF_QUALITY,
ID_DEF_QUALITY);
CLogFont.lfQuality = DEFAULT_QUALITY;
break;
case ID_FIXED:
CheckRadioButton(hDlg, ID_FIXED, ID_DEF_PITCH, ID_FIXED);
CLogFont.lfPitchAndFamily =
(~3 & CLogFont.lfPitchAndFamily) | FIXED_PITCH;
break;
case ID_VARIABLE:
CheckRadioButton(hDlg, ID_FIXED, ID_DEF_PITCH, ID_VARIABLE);
CLogFont.lfPitchAndFamily =
(~3 & CLogFont.lfPitchAndFamily) | VARIABLE_PITCH;
break;
case ID_DEF_PITCH:
CheckRadioButton(hDlg, ID_FIXED, ID_DEF_PITCH,
ID_DEF_PITCH);
CLogFont.lfPitchAndFamily =
(~3 & CLogFont.lfPitchAndFamily) | DEFAULT_PITCH;
break;
case ID_ROMAN:
CheckRadioButton(hDlg, ID_ROMAN, ID_DEF_FAMILY, ID_ROMAN);
CLogFont.lfPitchAndFamily =
(~240 & CLogFont.lfPitchAndFamily) | FF_ROMAN;
break;
case ID_SWISS:
CheckRadioButton(hDlg, ID_ROMAN, ID_DEF_FAMILY, ID_SWISS);
CLogFont.lfPitchAndFamily =
(~240 & CLogFont.lfPitchAndFamily) | FF_SWISS;
break;
case ID_MODERN:
CheckRadioButton(hDlg, ID_ROMAN, ID_DEF_FAMILY, ID_MODERN);
CLogFont.lfPitchAndFamily =
(~240 & CLogFont.lfPitchAndFamily) | FF_MODERN;
break;
case ID_SCRIPT:
CheckRadioButton(hDlg, ID_ROMAN, ID_DEF_FAMILY, ID_SCRIPT);
CLogFont.lfPitchAndFamily =
(~240 & CLogFont.lfPitchAndFamily) | FF_SCRIPT;
break;
case ID_DECO:
CheckRadioButton(hDlg, ID_ROMAN, ID_DEF_FAMILY, ID_DECO);
CLogFont.lfPitchAndFamily =
(~240 & CLogFont.lfPitchAndFamily) | FF_DECORATIVE;
break;
case ID_DEF_FAMILY:
CheckRadioButton(hDlg, ID_ROMAN, ID_DEF_FAMILY,
ID_DEF_FAMILY);
CLogFont.lfPitchAndFamily =
(~240 & CLogFont.lfPitchAndFamily) | FF_DONTCARE;
break;
}
break;
}
return (FALSE);
}
CLIDATA.C
CD-ROM Disc Path: \SAMPCODE\WIN_SDK\DDE\CLIDATA.C
/****************************************************************************
MODULE: CLIDATA.C
PURPOSE: Maintains conversation data and paints data in the client
application window.
****************************************************************************/
#include "windows.h"
#include "clires.h"
#include "client.h"
#include <string.h>
#include <stdlib.h>
typedef struct ITEM
{
char szItem[ITEM_MAX_SIZE+1];
char szValue[VALUE_MAX_SIZE+1];
};
typedef struct CONV
{
BOOL bInTerminate;
enum PENDINGACK ePendingAck;
HWND hwndClientDDE;
HWND hwndServerDDE;
char szApplication[APP_MAX_SIZE+1];
char szTopic[TOPIC_MAX_SIZE+1];
int nItemCount;
struct ITEM Item[ITEMS_PER_CONV_MAX_COUNT];
};
static struct CONV Conv[CONV_MAX_COUNT];
static int nConvCount = 0;
static HWND hwndNewClientDDE; /* used by SelectNewConvDlgProc */
static HWND hwndNewServerDDE; /* new conversation selected by user */
static char szSelectedApplication[APP_MAX_SIZE+1];
static char szSelectedTopic[TOPIC_MAX_SIZE+1];
static char szSelectedItem[ITEM_MAX_SIZE+1];
static char szSelectedValue[VALUE_MAX_SIZE+1];
static struct CONV * NEAR FindConv(HWND);
static struct ITEM * NEAR FindItem(HWND, char *);
BOOL FAR PASCAL SelectNewConvDlgProc(HWND, unsigned, WORD, LONG);
/*****************************************************************
FUNCTION: AddItemToConv
PURPOSE: Add a data item to an existing conversation.
*****************************************************************/
BOOL AddItemToConv(hwndClientDDE, szItem)
HWND hwndClientDDE;
char * szItem;
{
struct CONV * pConv;
struct ITEM * pItem;
if (!(pConv = FindConv(hwndClientDDE)))
return (FALSE);
if (pConv->nItemCount >= ITEMS_PER_CONV_MAX_COUNT)
return (FALSE);
pItem = pConv->Item + pConv->nItemCount++;
strcpy(pItem->szItem, szItem);
pItem->szValue[0] = 0;
return (TRUE);
}
/**********************************************************
FUNCTION: AtLeastOneConvActive
PURPOSE: Used during termination of application, to
determine whether pending DDE terminations
have completed.
***********************************************************/
BOOL AtLeastOneConvActive()
{
return (nConvCount? TRUE: FALSE);
}
/*****************************************************************
FUNCTION: AddConv
PURPOSE: Initialize items in CONV structure.
*****************************************************************/
BOOL AddConv(hwndClientDDE, hwndServerDDE, szApplication, szTopic)
HWND hwndClientDDE;
HWND hwndServerDDE;
char * szApplication;
char * szTopic;
{
struct CONV * pConv;
if (nConvCount >= CONV_MAX_COUNT)
return (FALSE);
pConv = Conv + nConvCount++;
pConv->bInTerminate = FALSE;
pConv->ePendingAck = NONE;
pConv->hwndClientDDE = hwndClientDDE;
pConv->hwndServerDDE = hwndServerDDE;
strcpy(pConv->szApplication, szApplication);
strcpy(pConv->szTopic, szTopic);
pConv->nItemCount = 0;
return (TRUE);
}
/*****************************************************************
FUNCTION: DoesAdviseAlreadyExist
PURPOSE: Determines whether hot/warm link has already been
established for specified conversation item.
*****************************************************************/
BOOL DoesAdviseAlreadyExist(hwndClientDDE, szItem)
HWND hwndClientDDE;
char * szItem;
{
return (FindItem(hwndClientDDE,szItem)==NULL?FALSE:TRUE);
}
/*****************************************************************
FUNCTION: FindItem
PURPOSE: Return pointer to item structure given conversation and item.
*****************************************************************/
struct ITEM * NEAR FindItem(hwndClientDDE, szItem)
HWND hwndClientDDE;
char * szItem;
{
struct CONV * pConv;
struct ITEM * pItem;
int nItemIndex;
if (!(pConv = FindConv(hwndClientDDE)))
return (NULL);
for (pItem = pConv->Item, nItemIndex = 0;
nItemIndex < pConv->nItemCount;
pItem++, nItemIndex++)
{
if (!strcmpi(szItem, pItem->szItem))
{
return (pItem);
}
}
return (NULL);
}
/*****************************************************************
FUNCTION: FindConv
PURPOSE: Return pointer to conversation structure given handle
to client DDE window.
*****************************************************************/
struct CONV * NEAR FindConv(hwndClientDDE)
HWND hwndClientDDE;
{
struct CONV * pConv;
int nConvIndex;
for (pConv = Conv, nConvIndex = 0;
nConvIndex < nConvCount;
pConv++, nConvIndex++)
{
if (pConv->hwndClientDDE == hwndClientDDE)
return (pConv);
}
return (NULL);
}
/***************************************************************
FUNCTION: FindConvGivenAppTopic
PURPOSE: Find handle of client DDE window given
application and topic for an active conversation.
***************************************************************/
HWND FindConvGivenAppTopic(szApp, szTopic)
char * szApp;
char * szTopic;
{
struct CONV * pConv;
int nConvIndex;
for (pConv = Conv, nConvIndex = 0;
nConvIndex < nConvCount;
pConv++, nConvIndex++)
{
if (!(stricmp(pConv->szApplication, szApp))
&& !(stricmp(pConv->szTopic, szTopic)))
{
return pConv->hwndClientDDE;
}
}
return NULL;
}
/*****************************************************************
FUNCTION: GetAppAndTopic
PURPOSE: Get conversation's application and topic strings.
*****************************************************************/
void GetAppAndTopic(hwndClientDDE, szApp, szTopic)
HWND hwndClientDDE;
char * szApp;
char * szTopic;
{
struct CONV * pConv;
if (!(pConv = FindConv(hwndClientDDE)))
return;
strcpy(szApp, pConv->szApplication);
strcpy(szTopic, pConv->szTopic);
return;
}
/****************************************************************
FUNCTION: GetConvPendingAck
PURPOSE: Return state of acknowledgement for specified
conversation.
****************************************************************/
enum PENDINGACK GetConvPendingAck(hwndClientDDE)
HWND hwndClientDDE;
{
struct CONV * pConv;
if (pConv = FindConv(hwndClientDDE))
return pConv->ePendingAck;
else
return NONE;
}
/*****************************************************************
FUNCTION: GetHwndServerDDE
PURPOSE: Gets the hwnd of the server, given the handle of
the client DDE window.
*****************************************************************/
HWND GetHwndServerDDE(hwndClientDDE)
HWND hwndClientDDE;
{
struct CONV * pConv;
int nConvIndex;
for (pConv = Conv, nConvIndex = 0;
nConvIndex < nConvCount;
pConv++, nConvIndex++)
{
if (pConv->hwndClientDDE == hwndClientDDE)
return (pConv->hwndServerDDE);
}
return (NULL);
}
/*****************************************************************
FUNCTION: GetNextConv
PURPOSE: Get next conversation in the list of current conversations.
To get the first conversation, pass a NULL hwnd.
*****************************************************************/
HWND GetNextConv(hwndClientDDE)
HWND hwndClientDDE;
{
struct CONV * pConv;
int nConvIndex;
if (hwndClientDDE)
{
for (nConvIndex = 0, pConv = Conv;
nConvIndex < nConvCount;
nConvIndex++, pConv++)
{
if (pConv->hwndClientDDE == hwndClientDDE)
{
if (++nConvIndex < nConvCount)
return (++pConv)->hwndClientDDE;
else
return (NULL);
}
}
return (NULL);
}
if (nConvCount > 0)
return (Conv[0].hwndClientDDE);
else
return (NULL);
}
/****************************************************************
FUNCTION: HexToInt
PURPOSE: Convert from ascii to integer up to 4 chars
representing a hexidecimal number. The hex number
is considered terminated by a null or any non-hex
digit.
****************************************************************/
int HexToInt(szHex)
char * szHex;
{
unsigned int nReturn;
int nDigit;
int nIndex;
nReturn = 0;
for (nIndex = 0; nIndex < 4; nIndex++)
{
if (*szHex >= '0' && *szHex <= '9')
nDigit = *szHex - '0';
else if (*szHex >= 'A' && *szHex <= 'F')
nDigit = *szHex - 'A' + 10;
else if (*szHex >= 'a' && *szHex <= 'f')
nDigit = *szHex - 'a' + 10;
else
return ((int)nReturn);
nReturn = (nReturn<<4) + nDigit;
szHex++;
}
return ((int)nReturn);
}
/****************************************************************
FUNCTION: IsConvInTerminateState
PURPOSE: Determine whether conversation is in process of
being terminated. In identifying the conversation,
it is necessary to compare both the hwndClientDDE
and hwndServerDDE, because during an initiate,
there may be multiple unwanted conversations sharing
the same hwndClientDDE.
****************************************************************/
BOOL IsConvInTerminateState(hwndClientDDE, hwndServerDDE)
HWND hwndClientDDE;
HWND hwndServerDDE;
{
struct CONV * pConv;
int nConvIndex;
for (nConvIndex = 0, pConv = Conv;
nConvIndex < nConvCount;
nConvIndex++, pConv++)
{
if (pConv->hwndClientDDE == hwndClientDDE
&& pConv->hwndServerDDE == hwndServerDDE)
return pConv->bInTerminate;
}
return (TRUE); /* If conversation not found, assume terminate state */
/* to avoid possible endless terminate feedback loop */
}
/****************************************************************
FUNCTION: IsHwndClientDDEUsed
PURPOSE: Determine whether hwndClientDDE is still being
used in some second conversation after the
first conversation has been terminated. This
determination is necessary during an initiate
in which the same hwndClientDDE is used in
multiple WM_DDE_INITIATE messages.
being terminated.
****************************************************************/
BOOL IsHwndClientDDEUsed(hwndClientDDE)
HWND hwndClientDDE;
{
struct CONV * pConv;
int nConvIndex;
for (pConv = Conv, nConvIndex = 0;
nConvIndex < nConvCount;
pConv++, nConvIndex++)
{
if (pConv->hwndClientDDE == hwndClientDDE)
return (TRUE);
}
return (FALSE);
}
/****************************************************************
FUNCTION: LetUserPickConversation
PURPOSE: The client has initiated possibly multiple
conversations (if a wild card application or topic
was specified in the WM_DDE_INITIATE). This function
determines whether multiple servers established
conversations with the specified hwndClientDDE.
If so, this function asks the user to pick one of
the conversations, and terminates the other
conversations.
****************************************************************/
BOOL LetUserPickConversation(hwndClientDDE)
HWND hwndClientDDE;
{
struct CONV * pConv;
FARPROC lpfnDlgProc;
int nCountSameWnd;
int nConvIndex;
nCountSameWnd = 0;
for (pConv = Conv, nConvIndex = 0;
nConvIndex < nConvCount;
pConv++, nConvIndex++)
{
if (pConv->hwndClientDDE == hwndClientDDE)
nCountSameWnd++;
}
if (nCountSameWnd == 1)
return (TRUE);
if (nCountSameWnd == 0)
return (FALSE);
hwndNewServerDDE = NULL;
hwndNewClientDDE = hwndClientDDE; /* make known to SelectNewConvDlgProc *
/* Dialog proc SelectNewConvDlgProc is defined in this module */
lpfnDlgProc = MakeProcInstance(SelectNewConvDlgProc, hInst);
DialogBox(hInst,
"SelectNewConversation",
hwndMain,
lpfnDlgProc);
FreeProcInstance(lpfnDlgProc);
/* Terminate unwanted conversations. The only conversation */
/* wanted is the one (hwndNewServerDDE) selected by the user */
/* in the SelectNewConv dialog box. */
for (pConv = Conv, nConvIndex = 0;
nConvIndex < nConvCount;
pConv++, nConvIndex++)
{
if (pConv->hwndClientDDE == hwndClientDDE
&& pConv->hwndServerDDE != hwndNewServerDDE)
{
SendTerminate(hwndClientDDE, pConv->hwndServerDDE);
}
}
return (TRUE);
}
/****************************************************************
FUNCTION: PaintConvData
PURPOSE: Paint the client application window, using all
conversation/item information.
****************************************************************/
void PaintConvData(hwnd)
HWND hwnd;
{
HDC hDC;
PAINTSTRUCT ps;
int x,y;
int nConvIndex, nItemIndex;
struct CONV * pConv;
struct ITEM * pItem;
char szNumber[10];
BeginPaint(hwnd, (LPPAINTSTRUCT)&ps);
hDC = ps.hdc;
y = yDelta/2; /* start 1/2 line down window */
for (pConv = Conv, nConvIndex = 0;
nConvIndex < nConvCount;
pConv++, nConvIndex++)
{
x = xDelta/2; /* start 1/2 char across window */
TextOut(hDC, x, y,
(LPSTR)pConv->szApplication,
strlen(pConv->szApplication));
x += ((3+APP_MAX_SIZE)*xDelta);
TextOut(hDC, x, y,
(LPSTR)pConv->szTopic,
strlen(pConv->szTopic));
x += ((3+TOPIC_MAX_SIZE) *xDelta);
itoa(pConv->hwndClientDDE, szNumber, 16);
strupr(szNumber);
TextOut(hDC, x, y, (LPSTR)szNumber, strlen(szNumber));
y += yDelta;
for (pItem = pConv->Item, nItemIndex = 0;
nItemIndex < pConv->nItemCount;
pItem++, nItemIndex++)
{
x = 4 * xDelta; /* Indent items 4 spaces */
TextOut(hDC, x, y,
(LPSTR)pItem->szItem,
strlen(pItem->szItem));
x += ((3+ITEM_MAX_SIZE)*xDelta);
TextOut(hDC, x, y,
(LPSTR)pItem->szValue,
strlen(pItem->szValue));
y += yDelta;
}
}
ValidateRect(hwnd, (LPRECT)NULL);
EndPaint(hwnd, (LPPAINTSTRUCT)&ps);
return;
}
/*****************************************************************
FUNCTION: RemoveItemFromConv
PURPOSE: Remove an item (advise) from an existing conversation.
*****************************************************************/
BOOL RemoveItemFromConv(hwndClientDDE, szItem)
HWND hwndClientDDE;
char * szItem;
{
struct CONV * pConv;
int nItemIndex;
struct ITEM * pItem;
if (!(pConv = FindConv(hwndClientDDE)))
return (FALSE);
pItem = pConv->Item;
nItemIndex = 0;
while (nItemIndex < pConv->nItemCount)
{
if (!(strcmpi(pItem->szItem, szItem)))
break;
pItem++;
nItemIndex++;
}
pConv->nItemCount--;
while (nItemIndex < pConv->nItemCount)
{
*pItem = *(pItem+1);
pItem++;
nItemIndex++;
}
return (TRUE);
}
/*****************************************************************
FUNCTION: RemoveConv
PURPOSE: Remove active conversation. It is necessary to
specify both the client and server DDE windows,
since during an initiate, only the server DDE
window handles are distinguishable.
*****************************************************************/
BOOL RemoveConv(hwndClientDDE, hwndServerDDE)
HWND hwndClientDDE;
HWND hwndServerDDE;
{
struct CONV * pRemoveConv;
struct CONV * pConv;
int nConvIndex;
for (pRemoveConv = Conv, nConvIndex = 0;
nConvIndex < nConvCount;
pRemoveConv++, nConvIndex++)
{
if (pRemoveConv->hwndClientDDE == hwndClientDDE
&& pRemoveConv->hwndServerDDE == hwndServerDDE)
break;
}
if (nConvIndex >= nConvCount)
return (FALSE);
nConvIndex = 0;
pConv = Conv;
while (pConv != pRemoveConv)
{
if (++nConvIndex >= nConvCount)
return (FALSE);
pConv++;
}
while (++nConvIndex < nConvCount)
{
*pConv = *(pConv+1);
pConv++;
}
nConvCount--;
return (TRUE);
}
/****************************************************************
FUNCTION: SelectNewConvDlgProc
PURPOSE: Ask the user to select one of multiple conversations
that were established during a wild card initiate.
****************************************************************/
BOOL FAR PASCAL SelectNewConvDlgProc(hdlg, message, wParam, lParam)
HWND hdlg;
unsigned message;
WORD wParam;
LONG lParam;
{
HWND hctlConvBox;
struct CONV * pConv;
int nConvIndex;
char szConvInfo[CONVINFO_MAX_SIZE];
char * pcBlank;
int nIndex;
switch (message)
{
case WM_INITDIALOG:
hctlConvBox = GetDlgItem(hdlg, IDC_CONVBOX);
SendMessage(hctlConvBox, LB_RESETCONTENT, 0, 0L);
for (pConv = Conv, nConvIndex = 0;
nConvIndex < nConvCount;
pConv++, nConvIndex++)
{
/* If this is one of the newly initiated conversations */
/* then add it to the list box. */
if (pConv->hwndClientDDE == hwndNewClientDDE)
{
/* Display server's DDE window in the list box, */
/* as that is the only way to distinguish */
/* conversations at this point. */
itoa((int)pConv->hwndServerDDE, szConvInfo, 16);
strupr(szConvInfo);
strcat(szConvInfo, " ");
strcat(szConvInfo, pConv->szApplication);
strcat(szConvInfo, " | ");
strcat(szConvInfo, pConv->szTopic);
SendMessage(hctlConvBox,
LB_ADDSTRING,
0,
(LONG)(LPSTR)szConvInfo);
}
}
return (TRUE);
case WM_COMMAND:
switch (wParam)
{
case IDC_CANCEL:
/* Function LetUserPickConveresation will terminate */
/* all newly initiated conversations. */
hwndNewServerDDE = NULL;
EndDialog(hdlg, FALSE);
return (TRUE);
case IDC_OK:
/* Function LetUserPickConversation will terminate */
/* all newly initiated conversations, except the */
/* one selected by the user: hwndNewServerDDE. */
hwndNewServerDDE = NULL;
hctlConvBox = GetDlgItem(hdlg, IDC_CONVBOX);
if ((nIndex = SendMessage(hctlConvBox,
LB_GETCURSEL, 0, 0L))
!= LB_ERR)
{
szConvInfo[0] = 0;
SendMessage(hctlConvBox,
LB_GETTEXT,
nIndex,
(LONG)(LPSTR)szConvInfo);
if (pcBlank = strchr(szConvInfo, ' '))
{
*pcBlank = 0; /* terminate hwnd numeric value */
hwndNewServerDDE = HexToInt(szConvInfo);
}
}
EndDialog(hdlg, TRUE);
return (TRUE);
default:
return (FALSE);
}
}
return (FALSE);
}
/****************************************************************
FUNCTION: SetConvInTerminateState
PURPOSE: Set conversation terminate state to TRUE.
****************************************************************/
void SetConvInTerminateState(hwndClientDDE, hwndServerDDE)
HWND hwndClientDDE;
HWND hwndServerDDE;
{
struct CONV * pConv;
int nConvIndex;
for (nConvIndex = 0, pConv = Conv;
nConvIndex < nConvCount;
nConvIndex++, pConv++)
{
if (pConv->hwndClientDDE == hwndClientDDE
&& pConv->hwndServerDDE == hwndServerDDE)
{
pConv->bInTerminate = TRUE;
return;
}
}
return;
}
/****************************************************************
FUNCTION: SetConvItemValue
PURPOSE: Find server data item and set value.
****************************************************************/
BOOL SetConvItemValue(hwndClientDDE, szItem, lpszValue)
HWND hwndClientDDE;
char * szItem;
LPSTR lpszValue;
{
struct ITEM * pItem;
char * pcValue;
if (pItem = FindItem(hwndClientDDE, szItem))
{
pcValue = pItem->szValue;
/* copy until <CR> in CF_TEXT data */
while (*lpszValue != '\r' && *lpszValue)
{
*pcValue++ = *lpszValue++;
}
*pcValue++ = 0;
/* Repaint client application window */
InvalidateRect(hwndMain, NULL, TRUE);
return (TRUE);
}
return (FALSE);
}
/****************************************************************
FUNCTION: SetConvPendingAck
PURPOSE: Set the state of acknowledgement for a specified
conversation.
****************************************************************/
void SetConvPendingAck(hwndClientDDE, ePendingAck)
HWND hwndClientDDE;
enum PENDINGACK ePendingAck;
{
struct CONV * pConv;
if (pConv = FindConv(hwndClientDDE))
{
pConv->ePendingAck = ePendingAck;
}
return;
}
CLIDDE.C
CD-ROM Disc Path: \SAMPCODE\WIN_SDK\DDE\CLIDDE.C
/****************************************************************************
MODULE: CLIDDE.C
PURPOSE: Processes incoming and outgoing DDE messages
****************************************************************************/
#include "windows.h"
#include "dde.h"
#include "clires.h"
#include "client.h"
#include <string.h>
#define DEFAULT_ACK_TIME_OUT_MILLISEC 10000
static int nAckTimeOut;
static BOOL bInInitiate = FALSE;
BOOL NEAR AwaitingAck(HWND);
/****************************************************************************
FUNCTION: AwaitingAck
PURPOSE: Inform user if acknowledgement is required before further
action.
****************************************************************************/
BOOL NEAR AwaitingAck(hwndClientDDE)
HWND hwndClientDDE;
{
if (GetConvPendingAck(hwndClientDDE) == NONE)
{
return (FALSE);
}
MessageBox(hwndMain,
"Previous DDE operation must be acknowledged first",
"Client",
MB_ICONEXCLAMATION | MB_OK);
return (TRUE);
}
/****************************************************************************
FUNCTION: ClientAcknowledge
PURPOSE: Called when client application receives WM_DDE_ACK message
or WM_TIMER message (time out on wait for ACK).
****************************************************************************/
void ClientAcknowledge(hwndClientDDE, hwndServerDDE, lParam, bTimeOut)
HWND hwndClientDDE;
HWND hwndServerDDE;
LONG lParam; /* lParam of WM_DDE_ACK message */
BOOL bTimeOut; /* TRUE if NACK is due to time-out */
{
enum PENDINGACK ePendingAck;
char szApplication[APP_MAX_SIZE+1];
char szTopic[TOPIC_MAX_SIZE+1];
char szItem[ITEM_MAX_SIZE+1];
char message[80];
ePendingAck = GetConvPendingAck(hwndClientDDE);
SetConvPendingAck(hwndClientDDE, NONE);
KillTimer(hwndClientDDE, hwndServerDDE);
if (bInInitiate)
{
GlobalGetAtomName(LOWORD(lParam),
szApplication,
APP_MAX_SIZE);
GlobalGetAtomName(HIWORD(lParam),
szTopic,
TOPIC_MAX_SIZE);
if (!AddConv(hwndClientDDE, hwndServerDDE, szApplication, szTopic))
{
MessageBox(hwndMain,
"Maximum conversation count exceeded",
"Client",
MB_ICONEXCLAMATION | MB_OK);
}
/*
GlobalDeleteAtom(LOWORD(lParam));
GlobalDeleteAtom(HIWORD(lParam));
*/
return;
}
if ((ePendingAck == ADVISE) && (LOWORD(lParam) & 0x8000))
{ /* received positive ACK in response to ADVISE */
GlobalGetAtomName(HIWORD(lParam), szItem, ITEM_MAX_SIZE);
AddItemToConv(hwndClientDDE, szItem);
/* Conversation item is established: now get current value */
/* and update screen */
SendRequest(hwndClientDDE, hwndServerDDE, szItem);
InvalidateRect(hwndMain, NULL, TRUE);
}
if ((ePendingAck == UNADVISE) && (LOWORD(lParam) & 0x8000))
{ /* received positive ACK in response to UNADVISE */
GlobalGetAtomName(HIWORD(lParam), szItem, ITEM_MAX_SIZE);
RemoveItemFromConv(hwndClientDDE, szItem);
InvalidateRect(hwndMain, NULL, TRUE);
}
if (!(LOWORD(lParam) & 0x8000)) /* NACK */
{
strcpy(message, "DDE ");
strcat(message, ePendingAck == ADVISE? "ADVISE "
: ePendingAck == UNADVISE? "UNADVISE "
: ePendingAck == POKE? "POKE "
: ePendingAck == REQUEST? "REQUEST "
: ePendingAck == EXECUTE? "EXECUTE "
: " ");
strcat(message, bTimeOut? "acknowledge time out"
: "operation failed");
MessageBox(hwndMain,
message,
"Client",
MB_ICONEXCLAMATION | MB_OK);
}
switch (ePendingAck)
{
case ADVISE:
case UNADVISE:
case POKE:
case REQUEST:
if (HIWORD(lParam)) /* will not be available for time-out */
GlobalDeleteAtom(HIWORD(lParam));
break;
case EXECUTE:
GlobalFree(HIWORD(lParam)); /* hCommand (execute string) */
break;
}
return;
}
/****************************************************************************
FUNCTION: ClientReceiveData
PURPOSE: Called when client application receives WM_DDE_DATA message.
****************************************************************************/
void ClientReceiveData(hwndClientDDE, hwndServerDDE, lParam)
HWND hwndClientDDE;
HWND hwndServerDDE;
LONG lParam;
{
DDEDATA FAR * lpDDEData;
char szItem[ITEM_MAX_SIZE+1];
BOOL bRelease;
BOOL bAck;
if (IsConvInTerminateState(hwndClientDDE, hwndServerDDE))
{ /* Terminate in progress: do not receive data */
GlobalFree(LOWORD(lParam));
GlobalDeleteAtom(HIWORD(lParam));
return;
}
if (GetConvPendingAck(hwndClientDDE) == REQUEST)
{
SetConvPendingAck(hwndClientDDE, NONE);
KillTimer(hwndClientDDE, hwndServerDDE);
}
if (!(lpDDEData = (DDEDATA FAR *)GlobalLock(LOWORD(lParam)))
|| (lpDDEData->cfFormat != CF_TEXT))
{
PostMessage(hwndServerDDE,
WM_DDE_ACK,
hwndClientDDE,
MAKELONG(0, HIWORD(lParam))); /* Negative ACK */
}
bAck = FALSE;
if (IsInRequestDlg())
{
/* Update REQUEST dialog box value */
RequestSatisfied(lpDDEData->Value);
bAck = TRUE;
}
else
{
GlobalGetAtomName(HIWORD(lParam), szItem, ITEM_MAX_SIZE);
bAck = SetConvItemValue(hwndClientDDE, szItem, lpDDEData->Value);
}
if (lpDDEData->fAckReq)
{
/* return ACK or NACK */
PostMessage(hwndServerDDE,
WM_DDE_ACK,
hwndClientDDE,
MAKELONG( (bAck? 0x8000:0), HIWORD(lParam)));
}
bRelease = lpDDEData->fRelease;
GlobalUnlock(LOWORD(lParam));
if (bRelease)
GlobalFree(LOWORD(lParam));
return;
}
/****************************************************************************
FUNCTION: ClientTerminate
PURPOSE: Called when client application receives WM_DDE_TERMINATE
message.
****************************************************************************/
void ClientTerminate(hwndClientDDE, hwndServerDDE)
HWND hwndClientDDE;
HWND hwndServerDDE;
{
if (!IsConvInTerminateState(hwndClientDDE, hwndServerDDE))
{ /* Server has requested terminate: respond with terminate */
PostMessage(hwndServerDDE, WM_DDE_TERMINATE, hwndClientDDE, 0L);
}
RemoveConv(hwndClientDDE, hwndServerDDE);
if (!IsHwndClientDDEUsed(hwndClientDDE))
DestroyWindow(hwndClientDDE);
InvalidateRect(hwndMain, NULL, TRUE);
return;
}
/****************************************************************************
FUNCTION: DDEWndProc
PURPOSE: Handles all DDE messages received by the client application.
****************************************************************************/
long FAR PASCAL DDEWndProc(hwnd, message, wParam, lParam)
HWND hwnd;
unsigned message;
WORD wParam;
LONG lParam;
{
switch (message)
{
case WM_DDE_ACK:
ClientAcknowledge(hwnd,(HWND)wParam, lParam, FALSE);
return (0L);
case WM_TIMER:
/* Negative ACK because of time out */
ClientAcknowledge(hwnd,(HWND)wParam, 0L, TRUE);
return (0L);
case WM_DDE_DATA:
ClientReceiveData(hwnd,(HWND)wParam, lParam);
return (0L);
case WM_DDE_TERMINATE:
ClientTerminate(hwnd,(HWND)wParam);
return (0L);
default:
return (DefWindowProc(hwnd, message, wParam, lParam));
}
}
/****************************************************************************
FUNCTION: DoPasteLink
PURPOSE: Get conversation information (app/topic/item) from clipboard.
Initiate conversation, if not already initiated.
Then, request server to advise the specified item.
Note, the standard clipboard format registered with the
name "Link" is as follows:
<app> <null> <topic> <null> <item> <null> <null>
****************************************************************************/
void DoPasteLink(void)
{
HANDLE hData;
LPSTR lpData;
HWND hwndClientDDE;
HWND hwndServerDDE;
char szApplication[APP_MAX_SIZE+1];
char szTopic[TOPIC_MAX_SIZE+1];
char szItem[ITEM_MAX_SIZE+1];
int nBufLen;
if (OpenClipboard(hwndMain))
{
if (!(hData = GetClipboardData(cfLink)) ||
!(lpData = GlobalLock(hData)))
{
CloseClipboard();
return;
}
/* Parse clipboard data */
if ((nBufLen = lstrlen(lpData)) >= APP_MAX_SIZE)
{
CloseClipboard();
GlobalUnlock(hData);
return;
}
lstrcpy(szApplication, lpData);
lpData += (nBufLen+1); /* skip over null */
if ((nBufLen = lstrlen(lpData)) >= TOPIC_MAX_SIZE)
{
CloseClipboard();
GlobalUnlock(hData);
return;
}
lstrcpy(szTopic, lpData);
lpData += (nBufLen+1); /* skip over null */
if ((nBufLen = lstrlen(lpData)) >= ITEM_MAX_SIZE)
{
CloseClipboard();
GlobalUnlock(hData);
return;
}
lstrcpy(szItem, lpData);
GlobalUnlock(hData);
CloseClipboard();
if (hwndClientDDE = FindConvGivenAppTopic(szApplication, szTopic))
{ /* app/topic conversation already started */
if (DoesAdviseAlreadyExist(hwndClientDDE, szItem))
MessageBox(hwndMain,"Advisory already established",
"Client", MB_ICONEXCLAMATION | MB_OK);
else
hwndServerDDE = GetHwndServerDDE(hwndClientDDE);
SendAdvise(hwndClientDDE, hwndServerDDE, szItem);
}
else
{ /* must initiate new conversation first */
SendInitiate(szApplication, szTopic);
if (hwndClientDDE = FindConvGivenAppTopic(szApplication, szTopic))
{
hwndServerDDE = GetHwndServerDDE(hwndClientDDE);
SendAdvise(hwndClientDDE, hwndServerDDE, szItem);
}
}
}
return;
}
/****************************************************************************
FUNCTION: InitAckTimeOut
PURPOSE: Get DDE timeout value from win.ini. Value is in milliseconds.
****************************************************************************/
void InitAckTimeOut(void)
{
/* Finds value in win.ini section corresponding to application name */
nAckTimeOut = GetPrivateProfileInt("Client",
"DdeTimeOut",
DEFAULT_ACK_TIME_OUT_MILLISEC,
"client.ini");
return;
}
/****************************************************************************
FUNCTION: SendAdvise
PURPOSE: Send advise message to server.
****************************************************************************/
void SendAdvise(hwndClientDDE, hwndServerDDE, szItem)
HWND hwndClientDDE;
HWND hwndServerDDE;
char * szItem;
{
ATOM atomItem;
HANDLE hOptions;
DDEADVISE FAR * lpOptions;
/* don't send another message requiring an ACK until first message */
/* is acknowledged */
if (AwaitingAck(hwndClientDDE))
return;
if (!(hOptions
= GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, (LONG)sizeof(DDEADVISE
return;
if (!(lpOptions
= (DDEADVISE FAR *)GlobalLock(hOptions)))
{
GlobalFree(hOptions);
return;
}
lpOptions->cfFormat = CF_TEXT;
lpOptions->fAckReq = TRUE;
lpOptions->fDeferUpd = FALSE;
GlobalUnlock(hOptions);
atomItem = GlobalAddAtom((LPSTR)szItem);
SetConvPendingAck(hwndClientDDE, ADVISE);
SetTimer(hwndClientDDE, hwndServerDDE, nAckTimeOut, NULL);
if (!PostMessage(hwndServerDDE,
WM_DDE_ADVISE,
hwndClientDDE,
MAKELONG(hOptions, atomItem)))
{
GlobalDeleteAtom(atomItem);
GlobalFree(hOptions);
}
return;
}
/****************************************************************************
FUNCTION: SendExecute
PURPOSE: Send execute string to server.
****************************************************************************/
void SendExecute(hwndClientDDE, hwndServerDDE, szExecuteString)
HWND hwndClientDDE;
HWND hwndServerDDE;
char * szExecuteString;
{
HANDLE hExecuteString;
LPSTR lpExecuteString;
/* don't send another message requiring an ACK until first message */
/* is acknowledged */
if (AwaitingAck(hwndClientDDE))
return;
if (!(hExecuteString
= GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE,
(DWORD)lstrlen(szExecuteString) + 1)))
return;
if (!(lpExecuteString
= GlobalLock(hExecuteString)))
{
GlobalFree(hExecuteString);
return;
}
lstrcpy(lpExecuteString, szExecuteString);
GlobalUnlock(hExecuteString);
SetConvPendingAck(hwndClientDDE, EXECUTE);
SetTimer(hwndClientDDE, hwndServerDDE, nAckTimeOut, NULL);
if (!PostMessage(hwndServerDDE,
WM_DDE_EXECUTE,
hwndClientDDE,
MAKELONG(0, hExecuteString)))
{
GlobalFree(hExecuteString);
}
return;
}
/****************************************************************************
FUNCTION: SendInitiate
PURPOSE: Sends initiate message to all windows. By the time this
function returns, all servers matching the app/topic will
have acknowledged, and this client applicaiton will have
temporarily registered the new conversations. If more
than one server responded, then this client application
asks the user which conversation to keep; all other
conversations will then be terminated. This function
returns the handle of the hidden DDE window used to
initiate the conversation with server(s).
****************************************************************************/
HWND SendInitiate(szApplication, szTopic)
char * szApplication;
char * szTopic;
{
HWND hwndClientDDE;
ATOM atomApplication;
ATOM atomTopic;
if (!(hwndClientDDE = CreateWindow(
"ClientDDEWndClass",
"ClientDDE",
WS_CHILD, /* not visible */
0, 0, 0, 0, /* no position or dimensions */
hwndMain, /* parent */
NULL, /* no menu */
hInst,
NULL)))
{
return (NULL);
}
atomApplication
= *szApplication == 0 ? NULL : GlobalAddAtom((LPSTR)szApplication);
atomTopic
= *szTopic == 0 ? NULL : GlobalAddAtom((LPSTR)szTopic);
/* flag bIniInitiate is queried when client processes the server's ACK */
bInInitiate = TRUE;
SendMessage(-1,
WM_DDE_INITIATE,
hwndClientDDE,
MAKELONG(atomApplication, atomTopic));
bInInitiate = FALSE;
if (atomApplication != NULL)
GlobalDeleteAtom(atomApplication);
if (atomTopic != NULL)
GlobalDeleteAtom(atomTopic);
return (hwndClientDDE);
}
/****************************************************************************
FUNCTION: SendPoke
PURPOSE: Send poke message to server.
****************************************************************************/
void SendPoke(hwndClientDDE, hwndServerDDE, szItem, szValue)
HWND hwndClientDDE;
HWND hwndServerDDE;
char * szItem;
char * szValue;
{
ATOM atomItem;
HANDLE hPokeData;
DDEPOKE FAR * lpPokeData;
/* don't send another message requiring an ACK until first message */
/* is acknowledged */
if (AwaitingAck(hwndClientDDE))
return;
/* Allocate size of DDE data header, plus the data: a string */
/* terminated by <CR> <LF> <NULL>. The <NULL> is counted by */
/* by DDEPOKE.Value[1]. */
if (!(hPokeData
= GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE,
(LONG)sizeof(DDEPOKE) + lstrlen(szValue) + 2)))
return;
if (!(lpPokeData
= (DDEPOKE FAR*)GlobalLock(hPokeData)))
{
GlobalFree(hPokeData);
return;
}
lpPokeData->fRelease = TRUE;
lpPokeData->cfFormat = CF_TEXT;
lstrcpy((LPSTR)lpPokeData->Value, (LPSTR)szValue);
/* each line of CF_TEXT data is terminated by CR/LF */
lstrcat((LPSTR)lpPokeData->Value, (LPSTR)"\r\n");
GlobalUnlock(hPokeData);
atomItem = GlobalAddAtom((LPSTR)szItem);
SetConvPendingAck(hwndClientDDE, POKE);
SetTimer(hwndClientDDE, hwndServerDDE, nAckTimeOut, NULL);
if (!PostMessage(hwndServerDDE,
WM_DDE_POKE,
hwndClientDDE,
MAKELONG(hPokeData, atomItem)))
{
GlobalDeleteAtom(atomItem);
GlobalFree(hPokeData);
}
return;
}
/****************************************************************************
FUNCTION: SendRequest
PURPOSE: Send request message to server.
****************************************************************************/
void SendRequest(hwndClientDDE, hwndServerDDE, szItem)
HWND hwndClientDDE;
HWND hwndServerDDE;
char * szItem;
{
ATOM atomItem;
/* don't send another message requiring an ACK until first message */
/* is acknowledged */
if (AwaitingAck(hwndClientDDE))
return;
atomItem = GlobalAddAtom((LPSTR)szItem);
SetConvPendingAck(hwndClientDDE, REQUEST);
SetTimer(hwndClientDDE, hwndServerDDE, nAckTimeOut, NULL);
if (!PostMessage(hwndServerDDE,
WM_DDE_REQUEST,
hwndClientDDE,
MAKELONG(CF_TEXT,atomItem)))
{
GlobalDeleteAtom(atomItem);
}
return;
}
/****************************************************************************
FUNCTION: SendTerminate
PURPOSE: Send terminate message to server.
****************************************************************************/
void SendTerminate(hwndClientDDE, hwndServerDDE)
HWND hwndClientDDE;
HWND hwndServerDDE;
{
MSG msg;
LONG lTimeOut;
SetConvInTerminateState(hwndClientDDE, hwndServerDDE);
PostMessage(hwndServerDDE, WM_DDE_TERMINATE, hwndClientDDE, 0L);
return;
}
/****************************************************************************
FUNCTION: SendUnadvise
PURPOSE: Send unadvise message to server.
****************************************************************************/
void SendUnadvise(hwndClientDDE, hwndServerDDE, szItem)
HWND hwndClientDDE;
HWND hwndServerDDE;
char * szItem;
{
ATOM atomItem;
/* don't send another message requiring an ACK until first message */
/* is acknowledged */
if (AwaitingAck(hwndClientDDE))
return;
atomItem = GlobalAddAtom((LPSTR)szItem);
SetConvPendingAck(hwndClientDDE, UNADVISE);
SetTimer(hwndClientDDE, hwndServerDDE, nAckTimeOut, NULL);
if (!PostMessage(hwndServerDDE,
WM_DDE_UNADVISE,
hwndClientDDE,
MAKELONG(0,atomItem)))
{
GlobalDeleteAtom(atomItem);
}
return;
}
/****************************************************************************
FUNCTION: TerminateConversations
PURPOSE: Processes WM_DESTROY message, terminates all conversations.
****************************************************************************/
void TerminateConversations(void)
{
HWND hwndClientDDE;
HWND hwndServerDDE;
LONG lTimeOut;
MSG msg;
/* Terminate each active conversation */
hwndClientDDE = NULL;
while (hwndClientDDE = GetNextConv(hwndClientDDE))
{
hwndServerDDE = GetHwndServerDDE(hwndClientDDE);
if (IsWindow(hwndServerDDE)) /* if server window still alive */
SendTerminate(hwndClientDDE, hwndServerDDE);
}
/* Wait for all conversations to terminate or for time out */
lTimeOut = GetTickCount() + (LONG)nAckTimeOut;
while (PeekMessage(&msg, NULL, WM_DDE_FIRST, WM_DDE_LAST, PM_REMOVE))
{
DispatchMessage (&msg);
if (msg.message == WM_DDE_TERMINATE)
{
if (!AtLeastOneConvActive())
break;
}
if (GetTickCount() > lTimeOut)
break;
}
return;
}
CLIENT.C
CD-ROM Disc Path: \SAMPCODE\WIN_SDK\DDE\CLIENT.C
/****************************************************************************
PROGRAM: CLIENT
PURPOSE: Illustrates client side of DDE conversation
MODULES:
CLIENT.C Window and dialog procedures.
CLIDATA.C Maintains conversation data.
CLIDDE.C Processes incoming and outgoing DDE messages.
****************************************************************************/
#include "windows.h"
#include "dde.h"
#include "clires.h"
#include "client.h"
#include <string.h>
#include <stdlib.h>
static int nInstCount;
static HWND hwndRequestDlg;
static BOOL bInInitiate = FALSE;
static BOOL bInRequestDlg = FALSE;
static BOOL bTerminating = FALSE;
static char szSelectedApplication[APP_MAX_SIZE+1];
static char szSelectedTopic[TOPIC_MAX_SIZE+1];
static char szSelectedItem[ITEM_MAX_SIZE+1];
static char szSelectedValue[VALUE_MAX_SIZE+1];
static HWND hwndSelectedClientDDE;
static int cfSelectedFormat;
long FAR PASCAL MainWndProc(HWND, unsigned, WORD, LONG);
BOOL InitApplication(HANDLE);
void InitAddedInstance(HANDLE, HANDLE);
BOOL InitInstance(HANDLE, int);
int NEAR DoDialog(char *, FARPROC);
BOOL FAR PASCAL AboutDlgProc(HWND, unsigned, WORD, LONG);
BOOL FAR PASCAL AdviseDlgProc(HWND, unsigned, WORD, LONG);
BOOL FAR PASCAL ClearDlgProc(HWND, unsigned, WORD, LONG);
BOOL FAR PASCAL ExecuteDlgProc(HWND, unsigned, WORD, LONG);
BOOL FAR PASCAL InitiateDlgProc(HWND, unsigned, WORD, LONG);
BOOL FAR PASCAL PokeDlgProc(HWND, unsigned, WORD, LONG);
BOOL FAR PASCAL RequestDlgProc(HWND, unsigned, WORD, LONG);
BOOL FAR PASCAL TerminateDlgProc(HWND, unsigned, WORD, LONG);
BOOL FAR PASCAL UnadviseDlgProc(HWND, unsigned, WORD, LONG);
void AddConversationsToBox(HWND, unsigned);
void NEAR GetSelectedConversation(HWND, unsigned, unsigned);
/****************************************************************************
FUNCTION: WinMain(HANDLE, HANDLE, LPSTR, int)
PURPOSE: Calls initialization functions and processes message loop
****************************************************************************/
int PASCAL WinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow)
HANDLE hInstance;
HANDLE hPrevInstance;
LPSTR lpCmdLine;
int nCmdShow;
{
MSG msg;
if (!hPrevInstance)
{
if (!InitApplication(hInstance))
return (FALSE);
}
else
{
InitAddedInstance(hInstance, hPrevInstance);
}
if (!InitInstance(hInstance, nCmdShow))
return (FALSE);
while (GetMessage(&msg, NULL, NULL, NULL))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (msg.wParam);
}
/****************************************************************************
FUNCTION: InitApplication(HANDLE)
PURPOSE: Initializes window data and registers window classes
****************************************************************************/
BOOL InitApplication(hInstance)
HANDLE hInstance;
{
WNDCLASS wc;
nInstCount = 1;
wc.style = NULL;
wc.lpfnWndProc = MainWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = "ClientMenu";
wc.lpszClassName = "ClientWClass";
if (!RegisterClass(&wc))
return (FALSE);
wc.style = NULL;
wc.lpfnWndProc = DDEWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = NULL;
wc.hCursor = NULL;
wc.hbrBackground = NULL;
wc.lpszMenuName = NULL;
wc.lpszClassName = "ClientDDEWndClass";
return (RegisterClass(&wc));
}
/****************************************************************************
FUNCTION: InitAddedInstance
PURPOSE: Increment instance counter.
****************************************************************************/
void InitAddedInstance(hInstance, hPrevInstance)
HANDLE hInstance;
HANDLE hPrevInstance;
{
GetInstanceData(hPrevInstance, (NPSTR)&nInstCount, sizeof(int));
nInstCount++;
return;
}
/****************************************************************************
FUNCTION: InitInstance(HANDLE, int)
PURPOSE: Saves instance handle and creates main window
****************************************************************************/
BOOL InitInstance(hInstance, nCmdShow)
HANDLE hInstance;
int nCmdShow;
{
HDC hDC;
TEXTMETRIC tm;
hInst = hInstance;
hwndMain = CreateWindow(
"ClientWClass",
"Client",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
hInstance,
NULL
);
if (!hwndMain)
return (FALSE);
InitDataTextMetrics();
InitAckTimeOut(); /* in module CLIDDE */
MoveWindow(hwndMain,
xDelta*(5+nInstCount),
((nInstCount-1)&1)*nVertRes/2 + yDelta*nInstCount,
xDelta*30,
yDelta*12,
FALSE);
if (!(cfLink = RegisterClipboardFormat("Link")))
return (FALSE);
ShowWindow(hwndMain, nCmdShow);
UpdateWindow(hwndMain);
return (TRUE);
}
/****************************************************************************
FUNCTION: MainWndProc(HWND, unsigned, WORD, LONG)
PURPOSE: Processes messages for client application.
DDE messages are handled by DDEWndProc in CLIDDE.C.
****************************************************************************/
long FAR PASCAL MainWndProc(hwnd, message, wParam, lParam)
HWND hwnd;
unsigned message;
WORD wParam;
LONG lParam;
{
char szApplication[APP_MAX_SIZE+1];
char szTopic[TOPIC_MAX_SIZE+1];
switch (message)
{
case WM_PAINT:
PaintConvData(hwnd);
return (0L);
case WM_INITMENU:
if (wParam == GetMenu(hwnd))
{
if (IsClipboardFormatAvailable(cfLink))
EnableMenuItem(wParam, IDM_PASTELINK, MF_ENABLED);
else
EnableMenuItem(wParam, IDM_PASTELINK, MF_GRAYED);
}
return (0L);
case WM_COMMAND:
switch (wParam)
{
case IDM_INITIATE:
/* If we are in the process of terminating, no new
conversations are allowed */
if (!bTerminating)
{
DoDialog("Initiate", InitiateDlgProc);
}
return 0L;
case IDM_TERMINATE:
DoDialog("Terminate", TerminateDlgProc);
return 0L;
case IDM_ADVISE:
DoDialog("Advise", AdviseDlgProc);
return 0L;
case IDM_UNADVISE:
DoDialog("Unadvise", UnadviseDlgProc);
return 0L;
case IDM_REQUEST:
DoDialog("Request", RequestDlgProc);
return 0L;
case IDM_POKE:
DoDialog("Poke", PokeDlgProc);
return 0L;
case IDM_PASTELINK:
DoPasteLink();
return 0L;
case IDM_CLEAR:
DoDialog("Clear", ClearDlgProc);
return 0L;
case IDM_EXECUTE:
DoDialog("Execute", ExecuteDlgProc);
return 0L;
case IDM_ABOUT:
DoDialog("About", AboutDlgProc);
break;
default:
return (DefWindowProc(hwnd, message, wParam, lParam));
}
break;
case WM_DESTROY:
/* Terminate all DDE conversations before destroying
client window */
bTerminating = TRUE;
TerminateConversations();
PostQuitMessage(0);
break;
default:
return (DefWindowProc(hwnd, message, wParam, lParam));
}
return (0L);
}
/****************************************************************************
FUNCTION: DoDialog
PURPOSE: Creates dialog given dialog i.d.
****************************************************************************/
int NEAR DoDialog(szDialog, lpfnDlgProc)
char * szDialog;
FARPROC lpfnDlgProc;
{
int nReturn;
lpfnDlgProc = MakeProcInstance(lpfnDlgProc, hInst);
nReturn = DialogBox(hInst,
szDialog,
hwndMain,
lpfnDlgProc);
FreeProcInstance(lpfnDlgProc);
return (nReturn);
}
/****************************************************************************
FUNCTION: AboutDlgProc(HWND, unsigned, WORD, LONG)
PURPOSE: Processes messages for "About" dialog box
****************************************************************************/
BOOL FAR PASCAL AboutDlgProc(hDlg, message, wParam, lParam)
HWND hDlg;
unsigned message;
WORD wParam;
LONG lParam;
{
switch (message) {
case WM_INITDIALOG:
return (TRUE);
case WM_COMMAND:
if (wParam == IDOK || wParam == IDCANCEL) {
EndDialog(hDlg, TRUE);
return (TRUE);
}
break;
}
return (FALSE);
}
/****************************************************************************
FUNCTION: AdviseDlgProc
PURPOSE: Processes messages for the Advise dialog.
****************************************************************************/
BOOL FAR PASCAL AdviseDlgProc(hdlg, message, wParam, lParam)
HWND hdlg;
unsigned message;
WORD wParam;
LONG lParam;
{
HWND hwndServerDDE;
switch (message)
{
case WM_INITDIALOG:
AddConversationsToBox(hdlg, CB_ADDSTRING);
return (TRUE);
case WM_COMMAND:
switch (wParam)
{
case IDC_OK:
GetSelectedConversation(hdlg, CB_GETCURSEL, CB_GETLBTEXT);
GetDlgItemText(hdlg,
IDC_ITEM,
(LPSTR)szSelectedItem,
ITEM_MAX_SIZE);
if (DoesAdviseAlreadyExist(hwndSelectedClientDDE,
szSelectedItem))
MessageBox(hdlg, "Advisory already established",
"Client", MB_ICONEXCLAMATION | MB_OK);
else
hwndServerDDE
= GetHwndServerDDE(hwndSelectedClientDDE);
SendAdvise(hwndSelectedClientDDE,
hwndServerDDE,
szSelectedItem);
return (TRUE);
case IDC_CANCEL:
EndDialog(hdlg, FALSE);
return (FALSE);
}
default:
return (FALSE);
}
return (FALSE);
}
/****************************************************************************
FUNCTION: ClearDlgProc
PURPOSE: Processes messages for the Clear dialog.
****************************************************************************/
BOOL FAR PASCAL ClearDlgProc(hdlg, message, wParam, lParam)
HWND hdlg;
unsigned message;
WORD wParam;
LONG lParam;
{
HWND hwndServerDDE;
HWND hctlItemBox;
int nIndex;
switch (message)
{
case WM_INITDIALOG:
AddConversationsToBox(hdlg, CB_ADDSTRING);
return (TRUE);
case WM_COMMAND:
switch (wParam)
{
case IDC_OK:
GetSelectedConversation(hdlg, CB_GETCURSEL, CB_GETLBTEXT);
GetDlgItemText(hdlg,
IDC_ITEM,
(LPSTR)szSelectedItem,
ITEM_MAX_SIZE);
hwndServerDDE = GetHwndServerDDE(hwndSelectedClientDDE);
SendUnadvise(hwndSelectedClientDDE,
hwndServerDDE,
szSelectedItem);
EndDialog(hdlg, TRUE);
return (TRUE);
case IDC_CANCEL:
EndDialog(hdlg, FALSE);
return (TRUE);
}
default:
return (FALSE);
}
return (FALSE);
}
/****************************************************************************
FUNCTION: ExecuteDlgProc
PURPOSE: Processes messages for the Execute dialog.
****************************************************************************/
BOOL FAR PASCAL ExecuteDlgProc(hdlg, message, wParam, lParam)
HWND hdlg;
unsigned message;
WORD wParam;
LONG lParam;
{
HWND hwndServerDDE;
char szExecuteString[EXECUTE_STRING_MAX_SIZE+1];
switch (message)
{
case WM_INITDIALOG:
AddConversationsToBox(hdlg, CB_ADDSTRING);
return (TRUE);
case WM_COMMAND:
switch (wParam)
{
case IDC_OK:
GetSelectedConversation(hdlg, CB_GETCURSEL, CB_GETLBTEXT);
GetDlgItemText(hdlg,
IDC_EXECUTE_STRING,
(LPSTR)szExecuteString,
EXECUTE_STRING_MAX_SIZE);
hwndServerDDE = GetHwndServerDDE(hwndSelectedClientDDE);
SendExecute(hwndSelectedClientDDE,
hwndServerDDE,
szExecuteString);
return (TRUE);
case IDC_CANCEL:
EndDialog(hdlg, FALSE);
return (TRUE);
}
default:
return (FALSE);
}
return (FALSE);
}
/****************************************************************************
FUNCTION: InitiateDlgProc
PURPOSE: Processes messages for the Initiate dialog.
****************************************************************************/
BOOL FAR PASCAL InitiateDlgProc(hdlg, message, wParam, lParam)
HWND hdlg;
unsigned message;
WORD wParam;
LONG lParam;
{
HWND hwndClientDDE;
switch (message)
{
case WM_INITDIALOG:
return (TRUE);
case WM_COMMAND:
switch (wParam)
{
case IDC_OK:
GetDlgItemText(hdlg,
IDC_APPLICATION,
(LPSTR)szSelectedApplication,
APP_MAX_SIZE);
GetDlgItemText(hdlg,
IDC_TOPIC,
(LPSTR)szSelectedTopic,
TOPIC_MAX_SIZE);
EndDialog(hdlg, TRUE);
if (hwndClientDDE
= SendInitiate(szSelectedApplication, szSelectedTopic))
{
LetUserPickConversation(hwndClientDDE);
InvalidateRect(hwndMain, NULL, TRUE);
}
return (TRUE);
case IDC_CANCEL:
EndDialog(hdlg, FALSE);
return (TRUE);
}
default:
return (FALSE);
}
return (FALSE);
}
/****************************************************************************
FUNCTION: PokeDlgProc
PURPOSE: Processes messages for the Poke dialog.
****************************************************************************/
BOOL FAR PASCAL PokeDlgProc(hdlg, message, wParam, lParam)
HWND hdlg;
unsigned message;
WORD wParam;
LONG lParam;
{
HWND hwndServerDDE;
switch (message)
{
case WM_INITDIALOG:
AddConversationsToBox(hdlg, CB_ADDSTRING);
return (TRUE);
case WM_COMMAND:
switch (wParam)
{
case IDC_OK:
GetSelectedConversation(hdlg, CB_GETCURSEL, CB_GETLBTEXT);
GetDlgItemText(hdlg,
IDC_ITEM,
(LPSTR)szSelectedItem,
ITEM_MAX_SIZE);
GetDlgItemText(hdlg,
IDC_VALUE,
(LPSTR)szSelectedValue,
VALUE_MAX_SIZE);
hwndServerDDE = GetHwndServerDDE(hwndSelectedClientDDE);
SendPoke(hwndSelectedClientDDE,
hwndServerDDE,
szSelectedItem,
szSelectedValue);
return (TRUE);
case IDC_CANCEL:
EndDialog(hdlg, FALSE);
return (TRUE);
}
default:
return (FALSE);
}
return (FALSE);
}
/****************************************************************************
FUNCTION: RequestDlgProc
PURPOSE: Processes messages for the Request dialog.
****************************************************************************/
BOOL FAR PASCAL RequestDlgProc(hdlg, message, wParam, lParam)
HWND hdlg;
unsigned message;
WORD wParam;
LONG lParam;
{
HWND hwndServerDDE;
switch (message)
{
case WM_INITDIALOG:
hwndRequestDlg = hdlg;
bInRequestDlg = TRUE;
AddConversationsToBox(hdlg, CB_ADDSTRING);
return (TRUE);
case WM_COMMAND:
switch (wParam)
{
case IDC_OK:
GetSelectedConversation(hdlg, CB_GETCURSEL, CB_GETLBTEXT);
GetDlgItemText(hdlg,
IDC_ITEM,
(LPSTR)szSelectedItem,
ITEM_MAX_SIZE);
hwndServerDDE = GetHwndServerDDE(hwndSelectedClientDDE);
SendRequest(hwndSelectedClientDDE,
hwndServerDDE,
szSelectedItem);
return (TRUE);
case IDC_CANCEL:
bInRequestDlg = FALSE;
EndDialog(hdlg, FALSE);
return (TRUE);
}
break;
case WM_DESTROY:
bInRequestDlg = FALSE;
return (FALSE);
default:
return (FALSE);
}
return (FALSE);
}
/****************************************************************************
FUNCTION: TerminateDlgProc
PURPOSE: Processes messages for the Terminate dialog.
****************************************************************************/
BOOL FAR PASCAL TerminateDlgProc(hdlg, message, wParam, lParam)
HWND hdlg;
unsigned message;
WORD wParam;
LONG lParam;
{
HWND hwndServerDDE;
switch (message)
{
case WM_INITDIALOG:
AddConversationsToBox(hdlg, LB_ADDSTRING);
return (TRUE);
case WM_COMMAND:
switch (wParam)
{
case IDC_OK:
GetSelectedConversation(hdlg, LB_GETCURSEL, LB_GETTEXT);
EndDialog(hdlg, TRUE);
hwndServerDDE = GetHwndServerDDE(hwndSelectedClientDDE);
SendTerminate(hwndSelectedClientDDE, hwndServerDDE);
return (TRUE);
case IDC_CANCEL:
EndDialog(hdlg, FALSE);
return (TRUE);
}
default:
return (FALSE);
}
return (FALSE);
}
/****************************************************************************
FUNCTION: UnadviseDlgProc
PURPOSE: Processes messages for the Unadvise dialog.
****************************************************************************/
BOOL FAR PASCAL UnadviseDlgProc(hdlg, message, wParam, lParam)
HWND hdlg;
unsigned message;
WORD wParam;
LONG lParam;
{
HWND hctlItemBox;
int nIndex;
HWND hwndServerDDE;
switch (message)
{
case WM_INITDIALOG:
AddConversationsToBox(hdlg, CB_ADDSTRING);
return (TRUE);
case WM_COMMAND:
switch (wParam)
{
case IDC_OK:
GetSelectedConversation(hdlg, CB_GETCURSEL, CB_GETLBTEXT);
GetDlgItemText(hdlg,
IDC_ITEM,
(LPSTR)szSelectedItem,
ITEM_MAX_SIZE);
hwndServerDDE = GetHwndServerDDE(hwndSelectedClientDDE);
SendUnadvise(hwndSelectedClientDDE,
hwndServerDDE,
szSelectedItem);
return (TRUE);
case IDC_CANCEL:
EndDialog(hdlg, FALSE);
return (TRUE);
}
default:
return (FALSE);
}
return (FALSE);
}
/****************************************************************
FUNCTION: AddConversationsToBox
PURPOSE: Add server, app, topic info to client list box
****************************************************************/
void AddConversationsToBox(hdlg, nAddMessage)
HWND hdlg;
unsigned nAddMessage; /* LB_ADDSTRING or CB_ADDSTRING */
{
HWND hwndClientDDE;
HWND hctlServerList;
char szConvInfo[CONVINFO_MAX_SIZE+1];
char szApp[APP_MAX_SIZE+1];
char szTopic[TOPIC_MAX_SIZE+1];
hctlServerList = GetDlgItem(hdlg, IDC_CONVBOX);
SendMessage(hctlServerList,
nAddMessage == LB_ADDSTRING ? LB_RESETCONTENT : CB_RESETCONTENT,
0,
0L);
hwndClientDDE = NULL;
while (1)
{
if (!(hwndClientDDE = GetNextConv(hwndClientDDE)))
break;
itoa((int)hwndClientDDE, szConvInfo, 16);
strupr(szConvInfo);
strcat(szConvInfo,"->");
itoa((int)GetHwndServerDDE(hwndClientDDE),
szConvInfo+strlen(szConvInfo),
16);
strcat(szConvInfo," ");
GetAppAndTopic(hwndClientDDE, szApp, szTopic);
strcat(szConvInfo, szApp);
strcat(szConvInfo, " | ");
strcat(szConvInfo, szTopic);
SendMessage(hctlServerList,
nAddMessage,
0,
(LONG)(LPSTR)szConvInfo);
}
if (nAddMessage == CB_ADDSTRING)
{
SendMessage(hctlServerList, CB_SETCURSEL, 0, 0L);
}
return;
}
/*********************************************************************
FUNCTION: IsInRequestDlg
PURPOSE: Returns whether the user is in the Request dialog or not.
*********************************************************************/
BOOL IsInRequestDlg()
{
return (bInRequestDlg);
}
/*********************************************************************
FUNCTION: GetSelectedConversation
PURPOSE: Gets the user's selection from the conversation list
box, and returns result in hwndSelectedClientDDE.
*********************************************************************/
void NEAR GetSelectedConversation(hdlg, nCurSelMessage, nGetTextMessage)
HWND hdlg;
unsigned nCurSelMessage;
unsigned nGetTextMessage;
{
HWND hctlConvBox;
int nIndex;
char szConvInfo[CONVINFO_MAX_SIZE+1];
char * pcBlank;
hctlConvBox = GetDlgItem(hdlg, IDC_CONVBOX);
if ((nIndex = SendMessage(hctlConvBox, nCurSelMessage, 0, 0L))
!= LB_ERR)
{
szConvInfo[0] = 0;
SendMessage(hctlConvBox,
nGetTextMessage,
nIndex,
(LONG)(LPSTR)szConvInfo);
/* find '-' in 'hwnd->hwnd' list box entry */
if (!(pcBlank = strchr(szConvInfo, '-')))
return;
*pcBlank = 0; /* terminate hwnd numeric value */
hwndSelectedClientDDE = HexToInt(szConvInfo);
}
return;
}
/****************************************************************
FUNCTION: InitDataTextMetrics
PURPOSE: Get font information
****************************************************************/
void InitDataTextMetrics()
{
HDC hDC;
TEXTMETRIC tm;
hDC = GetDC(hwndMain);
GetTextMetrics(hDC, (LPTEXTMETRIC)&tm);
nHorzRes = GetDeviceCaps(hDC, HORZRES);
nVertRes = GetDeviceCaps(hDC, VERTRES);
ReleaseDC(hwndMain, hDC);
yDelta = tm.tmHeight + tm.tmExternalLeading;
xDelta = tm.tmAveCharWidth;
return;
}
/*********************************************************************
FUNCTION: RequestSatisfied
PURPOSE: Updates Request dialog box with value requested from
server.
*********************************************************************/
void RequestSatisfied(lpszValue)
LPSTR lpszValue;
{
HWND hctlValue;
hctlValue = GetDlgItem(hwndRequestDlg, IDC_VALUE);
SetWindowText(hctlValue, lpszValue);
return;
}
/*********************************************************************
FUNCTION: SetSelectedValue
PURPOSE: Set specified value.
*********************************************************************/
void SetSelectedValue(lpszSelectedValue)
LPSTR lpszSelectedValue;
{
lstrcpy((LPSTR)szSelectedValue, lpszSelectedValue);
return;
}
CLIPTEXT.C
CD-ROM Disc Path: \SAMPCODE\WIN_SDK\CLIPTEXT\CLIPTEXT.C
/****************************************************************************
PROGRAM: Cliptext.c
PURPOSE: Demonstrates copying text to and from the clipboard
FUNCTIONS:
WinMain() - calls initialization function, processes message loop
InitApplication() - initializes window data and registers window
InitInstance() - saves instance handle and creates main window
MainWndProc() - processes messages
About() - processes messages for "About" dialog box
OutOfMemory() - displays warning message
****************************************************************************/
#include "windows.h"
#include "cliptext.h"
HANDLE hInst;
HANDLE hAccTable;
HWND hwnd;
HANDLE hText = NULL;
char szInitialClientAreaText[] =
"This program demonstrates the use of the Edit menu to copy and "
"paste text to and from the clipboard. Try using the Copy command "
"to move this text to the clipboard, and the Paste command to replace "
"this text with data from another application. \r\n\r\n"
"You might want to try running Notepad and Clipbrd alongside this "
"application so that you can watch the data exchanges take place. ";
HANDLE hData, hClipData; /* handles to clip data
LPSTR lpData, lpClipData; /* pointers to clip data
/****************************************************************************
FUNCTION: WinMain(HANDLE, HANDLE, LPSTR, int)
PURPOSE: calls initialization function, processes message loop
****************************************************************************/
int PASCAL WinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow)
HANDLE hInstance;
HANDLE hPrevInstance;
LPSTR lpCmdLine;
int nCmdShow;
{
MSG msg;
LPSTR lpszText;
if (!hPrevInstance)
if (!InitApplication(hInstance))
return (FALSE);
if (!InitInstance(hInstance, nCmdShow))
return (FALSE);
while (GetMessage(&msg, NULL, NULL, NULL)) {
/* Only translate message if it is not an accelerator message */
if (!TranslateAccelerator(hwnd, hAccTable, &msg)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return (msg.wParam);
}
/****************************************************************************
FUNCTION: InitApplication(HANDLE)
PURPOSE: Initializes window data and registers window class
****************************************************************************/
BOOL InitApplication(hInstance)
HANDLE hInstance;
{
WNDCLASS wc;
wc.style = NULL;
wc.lpfnWndProc = MainWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = "CliptextMenu";
wc.lpszClassName = "CliptextWClass";
return (RegisterClass(&wc));
}
/****************************************************************************
FUNCTION: InitInstance(HANDLE, int)
PURPOSE: Saves instance handle and creates main window
****************************************************************************/
BOOL InitInstance(hInstance, nCmdShow)
HANDLE hInstance;
int nCmdShow;
{
LPSTR lpszText;
hInst = hInstance;
hAccTable = LoadAccelerators(hInst, "ClipTextAcc");
if (!(hText
= GlobalAlloc(GMEM_MOVEABLE,(DWORD)sizeof(szInitialClientAreaText))
OutOfMemory();
return (FALSE);
}
if (!(lpszText = GlobalLock(hText))) {
OutOfMemory();
return (FALSE);
}
lstrcpy(lpszText, szInitialClientAreaText);
GlobalUnlock(hText);
hwnd = CreateWindow(
"CliptextWClass",
"Cliptext Sample Application",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
hInstance,
NULL
);
if (!hwnd)
return (FALSE);
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
return (TRUE);
}
/****************************************************************************
FUNCTION: MainWndProc(HWND, unsigned, WORD, LONG)
PURPOSE: Processes messages
MESSAGES:
WM_COMMAND - message from menu
WM_INITMENU - initialize menu
WM_PAINT - update window
WM_DESTROY - destroy window
COMMENTS:
WM_INITMENU - when this message is received, the application checks
to see if there is any text data in the clipboard, and enables or
disables the Paste menu item accordingly.
Seclecting the Copy menu item will send the text "Hello Windows" to
the clipboard.
Seclecting the Paste menu item will copy whatever text is in the
clipboard to the application window.
****************************************************************************/
long FAR PASCAL MainWndProc(hWnd, message, wParam, lParam)
HWND hWnd;
unsigned message;
WORD wParam;
LONG lParam;
{
FARPROC lpProcAbout;
HDC hDC;
HMENU hMenu;
PAINTSTRUCT ps;
RECT rectClient;
LPSTR lpszText;
switch (message) {
case WM_INITMENU:
if (wParam == GetMenu(hWnd)) {
if (OpenClipboard(hWnd)) {
if (IsClipboardFormatAvailable(CF_TEXT)
|| IsClipboardFormatAvailable(CF_OEMTEXT))
EnableMenuItem(wParam, IDM_PASTE, MF_ENABLED);
else
EnableMenuItem(wParam, IDM_PASTE, MF_GRAYED);
CloseClipboard();
return (TRUE);
}
else /* Clipboard is not available
return (FALSE);
}
return (TRUE);
case WM_COMMAND:
switch(wParam) {
case IDM_ABOUT:
lpProcAbout = MakeProcInstance(About, hInst);
DialogBox(hInst, "AboutBox", hWnd, lpProcAbout);
FreeProcInstance(lpProcAbout);
break;
/* file menu commands */
case IDM_NEW:
case IDM_OPEN:
case IDM_SAVE:
case IDM_SAVEAS:
case IDM_PRINT:
MessageBox (
GetFocus ()
, "Command not implemented."
, "ClipText Sample Application"
, MB_ICONASTERISK | MB_OK
);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
/* edit menu commands */
case IDM_UNDO:
case IDM_CLEAR:
MessageBox (
GetFocus ()
, "Command not implemented."
, "ClipText Sample Application"
, MB_ICONASTERISK | MB_OK
);
break;
case IDM_CUT:
case IDM_COPY:
if (hText != NULL) {
/* Allocate memory and copy the string to it */
if (!(hData
= GlobalAlloc(GMEM_MOVEABLE, GlobalSize (hText))
OutOfMemory();
return (TRUE);
}
if (!(lpData = GlobalLock(hData))) {
OutOfMemory();
return (TRUE);
}
if (!(lpszText = GlobalLock (hText))) {
OutOfMemory();
return (TRUE);
}
lstrcpy(lpData, lpszText);
GlobalUnlock(hData);
GlobalUnlock (hText);
/* Clear the current contents of the clipboard, and s
* the data handle to the new string.
*/
if (OpenClipboard(hWnd)) {
EmptyClipboard();
SetClipboardData(CF_TEXT, hData);
CloseClipboard();
}
hData = NULL;
if (wParam == IDM_CUT) {
GlobalFree (hText);
hText = NULL;
EnableMenuItem(GetMenu (hWnd), IDM_CUT, MF_GRAYED
EnableMenuItem(GetMenu(hWnd), IDM_COPY, MF_GRAYED
InvalidateRect (hWnd, NULL, TRUE);
UpdateWindow (hWnd);
}
}
return (TRUE);
case IDM_PASTE:
if (OpenClipboard(hWnd)) {
/* get text from the clipboard */
if (!(hClipData = GetClipboardData(CF_TEXT))) {
CloseClipboard();
break;
}
if (hText != NULL) {
GlobalFree(hText);
}
if (!(hText = GlobalAlloc(GMEM_MOVEABLE
, GlobalSize(hClipData)))
OutOfMemory();
CloseClipboard();
break;
}
if (!(lpClipData = GlobalLock(hClipData))) {
OutOfMemory();
CloseClipboard();
break;
}
if (!(lpszText = GlobalLock(hText))) {
OutOfMemory();
CloseClipboard();
break;
}
lstrcpy(lpszText, lpClipData);
GlobalUnlock(hClipData);
CloseClipboard();
GlobalUnlock(hText);
EnableMenuItem(GetMenu(hWnd), IDM_CUT, MF_ENABLED);
EnableMenuItem(GetMenu(hWnd), IDM_COPY, MF_ENABLED);
/* copy text to the application window */
InvalidateRect(hWnd, NULL, TRUE);
UpdateWindow(hWnd);
return (TRUE);
}
else
return (FALSE);
}
break;
case WM_SIZE:
InvalidateRect(hWnd, NULL, TRUE);
break;
case WM_PAINT:
hDC = BeginPaint (hWnd, &ps);
if (hText != NULL) {
if (!(lpszText = GlobalLock (hText))) {
OutOfMemory();
} else {
GetClientRect (hWnd, &rectClient);
DrawText (hDC, lpszText, -1, &rectClient
, DT_EXTERNALLEADING | DT_NOPREFIX | DT_WORDB
GlobalUnlock (hText);
}
}
EndPaint (hWnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return (DefWindowProc(hWnd, message, wParam, lParam));
}
return (NULL);
}
/****************************************************************************
FUNCTION: About(HWND, unsigned, WORD, LONG)
PURPOSE: Processes messages for "About" dialog box
MESSAGES:
WM_INITDIALOG - initialize dialog box
WM_COMMAND - Input received
****************************************************************************/
BOOL FAR PASCAL About(hDlg, message, wParam, lParam)
HWND hDlg;
unsigned message;
WORD wParam;
LONG lParam;
{
switch (message) {
case WM_INITDIALOG:
return (TRUE);
case WM_COMMAND:
if (wParam == IDOK
|| wParam == IDCANCEL) {
EndDialog(hDlg, TRUE);
return (TRUE);
}
break;
}
return (FALSE);
}
/****************************************************************************
FUNCTION: OutOfMemory(void)
PURPOSE: Displays warning message
****************************************************************************/
void OutOfMemory(void)
{
MessageBox(
GetFocus(),
"Out of Memory",
NULL,
MB_ICONHAND | MB_SYSTEMMODAL);
return;
}
CLOCK.C
CD-ROM Disc Path: \SAMPCODE\WIN_SDK\CLOCK\CLOCK.C
/***************************************************************************
* *
* PROGRAM : Clock.c *
* *
* PURPOSE : To give a demonstration on the use of a timer in a windows *
* application. *
* *
* MACROS : HourHandPos - Computes the hour hand position based on *
* both the hour and minute values. *
* *
* VertEquiv - Computes the raster line equivalent to the *
* given pixel value. *
* *
* HorzEquiv - Computes the pixel equivalent to the given *
* raster line value. *
* *
* FUNCTIONS : About - Dialog function for the About Dialog. *
* *
* ClockWndProc - Window function for the application. *
* *
* CreateTools - Creates brushes and pens to coincide with *
* the current system colors. *
* *
* DeleteTools - Destroys the brushes and pens created by *
* CreateTools. *
* *
* ClockCreate - Performs the necessary initialization for *
* drawing the clock correctly and gets the *
* initial time to be displayed by the clock. *
* *
* ClockSize - Resize the clock to the largest possible *
* circle that will fit in the client area. *
* *
* ClockTimer - Update the clock to reflect the most recent *
* time. *
* *
* ClockPaint - Paint the clock to display the most recent *
* time. *
* *
* DrawFace - Draws the clock face. *
* *
* DrawHand - Draws a thin hand with the specified brush *
* in the specified hand position. *
* *
* DrawFatHand - Draws a fat hand with the specified brush *
* in the specified hand position. *
* *
* CircleClock - Resizes clock rectangle to keep clock *
* circular. *
* *
* WinMain - Calls the initialization function, creates *
* the main application window, and enters the *
* message loop. *
* *
* ClockInit - Registers the application window class and *
* initializes the circle values for the clock *
* face. *
* *
***************************************************************************/
#include "windows.h"
#include "clock.h"
/* Structure for holding time (in hours, minutes, and seconds) */
typedef struct
{
int hour;
int minute;
int second;
} TIME;
extern void GetTime(TIME *); /* asm function to get current time */
TIME oTime; /* the time currently displayed on the clock
HBRUSH hbrForegnd; /* foreground brush -- system window text color
HBRUSH hbrBackgnd; /* background brush -- system window backbround color
HPEN hpenForegnd; /* foreground pen -- system window text color
HPEN hpenBackgnd; /* background pen -- system window background color
HANDLE hInst; /* instance of the CLOCK program being executed
BOOL bFirst = TRUE; /* TRUE if this is the 1st instance; FALSE otherwise
HANDLE hCirTab; /* Circle table for the circular clock face positions
POINT FAR *lpCirTab; /* Pointer to the circle table
int TimerID = 1; /* number used for timer-id
char szBuffer[BUFLEN]; /* buffer for stringtable data
RECT ClockRect; /* rectangle that EXACTLY bounds the clock face
long ClockRadius; /* clock face radius
POINT ClockCenter; /* clock face center
BOOL bIconic = FALSE; /* TRUE if clock is currently iconic; FALSE otherwise
int HorzRes; /* width of the display (in pixels)
int VertRes; /* height of the display (in raster lines)
long AspectH; /* number of pixels per decimeter on the display
long AspectV; /* number of raster lines per decimeter on the displa
/***************************************************************************
* *
* MACRO : HourHandPos (TIME) *
* *
* PURPOSE : Computes the hour hand position based on both the hour and *
* minute values in the given time record. *
* *
***************************************************************************/
#define HourHandPos(time) (time.hour * 5) + (time.minute /12)
/***************************************************************************
* *
* MACRO : VertEquiv (int) *
* *
* PURPOSE : Computes the raster line (vertical) equivalent to the given *
* pixel (horizontal) value. *
* *
***************************************************************************/
#define VertEquiv(lengthH) ((lengthH * AspectV) / AspectH)
/***************************************************************************
* *
* MACRO : HorzEquiv (int) *
* *
* PURPOSE : Computes the pixel (horizontal) equivalent to the given *
* raster line (vertical) value. *
* *
***************************************************************************/
#define HorzEquiv(lengthV) ((lengthV * AspectH) / AspectV)
/***************************************************************************
* *
* FUNCTION : About (HWND, unsigned, WORD, LONG) *
* *
* PURPOSE : Dialog function for the "About..." menu item dialog. *
* *
***************************************************************************/
BOOL FAR PASCAL About(hDlg, message, wParam, lParam)
HWND hDlg;
unsigned message;
WORD wParam;
LONG lParam;
{
switch (message)
{
case WM_COMMAND:
EndDialog(hDlg, TRUE);
/* fall through */
case WM_INITDIALOG:
return(TRUE);
default:
return(FALSE);
}
}
/***************************************************************************
* *
* FUNCTION : ClockWndProc (HWND, unsigned, WORD, LONG) *
* *
* PURPOSE : Window function for the application. *
* *
***************************************************************************/
long FAR PASCAL ClockWndProc(hWnd, message, wParam, lParam)
HWND hWnd;
unsigned message;
WORD wParam;
LONG lParam;
{
switch (message)
{
case WM_SYSCOMMAND:
if (wParam == IDM_ABOUT)
{
/* Draw and handle messages for the "About..." Dialog */
DialogBox(hInst,
MAKEINTRESOURCE(1),
hWnd,
MakeProcInstance((FARPROC) About, hInst));
}
else
{
/* Perform the default window processing */
return(DefWindowProc(hWnd, message, wParam, lParam));
}
break;
case WM_SIZE:
/* Resize clock based on window size and redraw */
ClockSize(hWnd, LOWORD(lParam), HIWORD(lParam), wParam);
UpdateWindow(hWnd);
break;
case WM_DESTROY:
/* Destroy clock's timer and tools before exiting */
KillTimer(hWnd, TimerID);
DeleteTools();
PostQuitMessage(0);
break;
case WM_PAINT:
{
PAINTSTRUCT ps;
/* Paint clock displaying current time */
InvalidateRect(hWnd, (LPRECT) NULL, TRUE);
BeginPaint(hWnd, (LPPAINTSTRUCT) &ps);
ClockPaint(hWnd, ps.hdc, PAINTALL);
EndPaint(hWnd, (LPPAINTSTRUCT) &ps);
}
break;
case WM_TIMECHANGE:
case WM_TIMER:
/* Update clock to display new time */
ClockTimer(hWnd);
break;
case WM_SYSCOLORCHANGE:
/* Change tools to coincide with system window colors */
DeleteTools();
CreateTools();
break;
case WM_ERASEBKGND:
{
RECT rc;
/* Paint over the entire client area */
GetClientRect(hWnd, (LPRECT) &rc);
FillRect((HDC) wParam, (LPRECT) &rc, hbrBackgnd);
}
break;
default:
/* Perform the default window processing */
return(DefWindowProc(hWnd, message, wParam, lParam));
}
return(0L);
}
/***************************************************************************
* *
* FUNCTION : CreateTools () *
* *
* PURPOSE : Creates brushes and pens to coincide with the current *
* system colors. *
* *
***************************************************************************/
int CreateTools()
{
hbrForegnd = CreateSolidBrush(GetSysColor(COLOR_WINDOWTEXT));
hbrBackgnd = CreateSolidBrush(GetSysColor(COLOR_WINDOW));
hpenForegnd = CreatePen(0, 1, GetSysColor(COLOR_WINDOWTEXT));
hpenBackgnd = CreatePen(0, 1, GetSysColor(COLOR_WINDOW));
}
/***************************************************************************
* *
* FUNCTION : DeleteTools () *
* *
* PURPOSE : Destroys the brushes and pens created by CreateTools. *
* *
***************************************************************************/
int DeleteTools()
{
DeleteObject(hbrForegnd);
DeleteObject(hbrBackgnd);
DeleteObject(hpenForegnd);
DeleteObject(hpenBackgnd);
}
/***************************************************************************
* *
* FUNCTION : ClockCreate () *
* *
* PURPOSE : First, for drawing the clock, ClockCreate computes the *
* aspect ratio and creates the necessary pens and brushes. *
* Then, if this is the first instance of the app running, *
* ClockCreate scales the circle table values according to the *
* aspect ratio. Finally, ClockCreate gets the initial time. *
* *
***************************************************************************/
int ClockCreate()
{
int pos; /* hand position index into the circle table */
int vertSize; /* height of the display in millimeters */
int horzSize; /* width of the display in millimeters */
HDC hDC;
RECT rc;
/* Get display size in (pixels X raster lines) */
/* and in (millimeters X millimeters) */
hDC = GetDC(NULL);
VertRes = GetDeviceCaps(hDC, VERTRES);
HorzRes = GetDeviceCaps(hDC, HORZRES);
vertSize= GetDeviceCaps(hDC, VERTSIZE);
horzSize= GetDeviceCaps(hDC, HORZSIZE);
ReleaseDC(NULL, hDC);
/* Compute (raster lines / decimeter) and (pixels / decimeter) */
AspectV = ((long) VertRes * MMPERDM) / (long) vertSize;
AspectH = ((long) HorzRes * MMPERDM) / (long) horzSize;
CreateTools();
/* Scale cosines for aspect ratio if this is the first instance */
if (bFirst)
{
lpCirTab = (POINT far *) GlobalLock(hCirTab);
for (pos = 0; pos < HANDPOSITIONS; pos++)
{
lpCirTab[pos].y = VertEquiv(lpCirTab[pos].y);
}
GlobalUnlock(hCirTab);
}
GetTime(&oTime);
}
/***************************************************************************
* *
* FUNCTION : ClockSize (HWND, int, int, WORD) *
* *
* PURPOSE : Resize the clock to the largest possible circle that will *
* fit in the client area. If switching from not iconic to *
* iconic, alter the timer to update every minute. And if *
* switching back to non iconic, restore the timer to update *
* every second. *
* *
***************************************************************************/
int ClockSize(hWnd, newWidth, newHeight, sizeType)
HWND hWnd;
int newWidth;
int newHeight;
WORD sizeType;
{
/* Set ClockRect to bound the largest possible circle in the window */
SetRect((LPRECT) &(ClockRect), 0, 0, newWidth, newHeight);
CircleClock(newWidth, newHeight);
if(sizeType == SIZEICONIC)
{
/* Update once every minute in the iconic state */
KillTimer(hWnd, TimerID);
SetTimer(hWnd, TimerID, (unsigned) ICON_TLEN, 0L);
bIconic = TRUE;
}
else if (bIconic)
{
/* Update every second in the opened state (ignore tiling) */
KillTimer(hWnd, TimerID);
SetTimer(hWnd, TimerID, OPEN_TLEN, 0L);
bIconic = FALSE;
}
}
/***************************************************************************
* *
* FUNCTION : ClockTimer (HWND) *
* *
* PURPOSE : Update the clock to reflect the most recent time. *
* *
***************************************************************************/
int ClockTimer(hWnd)
HWND hWnd;
{
TIME nTime;
HDC hDC;
GetTime(&nTime);
/* It's possible to change any part of the system at any time through */
/* the Control Panel. Check for any change in second, minute, or hour */
if ((nTime.second != oTime.second) ||
(nTime.minute != oTime.minute) ||
(nTime.hour != oTime.hour))
{
/* The time has changed -- update the clock */
hDC = GetDC(hWnd);
ClockPaint(hWnd, hDC, HANDPAINT);
ReleaseDC(hWnd, hDC);
}
}
/***************************************************************************
* *
* FUNCTION : ClockPaint (HWND, HDC, int) *
* *
* PURPOSE : Paint the clock to display the most recent time. *
* *
***************************************************************************/
int ClockPaint(hWnd, hDC, paintType)
HWND hWnd;
HDC hDC;
int paintType;
{
TIME nTime;
SetBkMode(hDC, TRANSPARENT);
lpCirTab = (POINT far *) GlobalLock(hCirTab);
if (paintType == PAINTALL)
{
/* Paint entire clock -- face and hands */
FillRect(hDC, (LPRECT) &ClockRect, hbrBackgnd);
DrawFace(hDC);
DrawFatHand(hDC, HourHandPos(oTime), hpenForegnd, HHAND);
DrawFatHand(hDC, oTime.minute, hpenForegnd, MHAND);
if (!bIconic)
{
/* Erase old second hand */
DrawHand(hDC, oTime.second, hpenBackgnd, SECONDTIP, R2_NOT);
}
}
else if (paintType == HANDPAINT)
{
GetTime(&nTime);
if ((!bIconic) && (nTime.second != oTime.second))
{
/* Second has changed -- erase old second hand */
DrawHand(hDC, oTime.second, hpenBackgnd, SECONDTIP, R2_NOT);
}
if ((nTime.minute != oTime.minute) || (nTime.hour != oTime.hour))
{
/* Hour and/or minute have changed -- update hands */
if (bIconic)
{
/* Erase old minute and hour hands */
DrawHand(hDC, oTime.minute,
hpenBackgnd, MINUTETIP, R2_COPYPEN);
DrawHand(hDC, HourHandPos(oTime),
hpenBackgnd, HOURTIP, R2_COPYPEN);
/* Draw new minute and hour hands */
DrawHand(hDC, nTime.minute,
hpenForegnd, MINUTETIP, R2_COPYPEN);
DrawHand(hDC, HourHandPos(nTime),
hpenForegnd, HOURTIP, R2_COPYPEN);
}
else
{
/* Erase old minute and hour fat hands */
DrawFatHand(hDC, oTime.minute,
hpenBackgnd, MHAND);
DrawFatHand(hDC, HourHandPos(oTime),
hpenBackgnd, HHAND);
/* Draw new minute and hour fat hands */
DrawFatHand(hDC, nTime.minute,
hpenForegnd, MHAND);
DrawFatHand(hDC, HourHandPos(nTime),
hpenForegnd, HHAND);
}
}
if ((!bIconic) && (nTime.second != oTime.second))
{
/* second has changed -- draw new second hand */
DrawHand(hDC, nTime.second,
hpenBackgnd, SECONDTIP, R2_NOT);
}
/* Store most recent time */
oTime.minute = nTime.minute;
oTime.hour = nTime.hour;
oTime.second = nTime.second;
}
GlobalUnlock(hCirTab);
}
/***************************************************************************
* *
* FUNCTION : DrawFace (HDC) *
* *
* PURPOSE : Draws the clock face. *
* *
***************************************************************************/
DrawFace(hDC)
HDC hDC; /* device context to be used when drawing face */
{
int pos; /* hand position index into the circle table */
int dotHeight; /* height of the hour-marking dot */
int dotWidth; /* width of the hour-marking dot */
POINT dotCenter; /* center point of the hour-marking dot */
RECT rc;
/* Compute hour-marking dot width, height, and center point */
dotWidth = (MAXDOTWIDTH * (long) (ClockRect.right - ClockRect.left)) / Horz
dotHeight = VertEquiv(dotWidth);
if (dotHeight < MINDOTHEIGHT)
{
dotHeight = MINDOTHEIGHT;
}
if (dotWidth < MINDOTWIDTH)
{
dotWidth = MINDOTWIDTH;
}
dotCenter.x = dotWidth >> 1;
dotCenter.y = dotHeight >> 1;
/* Compute the clock center and radius */
InflateRect((LPRECT) &ClockRect, -dotCenter.y, -dotCenter.x);
ClockRadius = (long) ((ClockRect.right - ClockRect.left) >> 1);
ClockCenter.x = ClockRect.left + ClockRadius;
ClockCenter.y = ClockRect.top + ((ClockRect.bottom - ClockRect.top) >> 1);
InflateRect((LPRECT) &ClockRect, dotCenter.y, dotCenter.x);
/* Draw the large hour-marking dots and small minute-marking dots */
for(pos = 0; pos < HANDPOSITIONS; pos++)
{
rc.top = (lpCirTab[pos].y * ClockRadius) / CIRTABSCALE + ClockCenter.y;
rc.left = (lpCirTab[pos].x * ClockRadius) / CIRTABSCALE + ClockCenter.x;
if (pos % 5)
{
if ((dotWidth > MINDOTWIDTH) && (dotHeight > MINDOTHEIGHT))
{
/* Draw small minute-marking dot */
rc.right = rc.left + 1;
rc.bottom = rc.top + 1;
FillRect(hDC, (LPRECT) &rc, hbrForegnd);
}
}
else
{
/* Draw large hour-marking dot */
rc.right = rc.left + dotWidth;
rc.bottom = rc.top + dotHeight;
OffsetRect((LPRECT) &rc, -dotCenter.x, -dotCenter.y);
FillRect(hDC, (LPRECT) &rc, hbrForegnd);
}
}
}
/***************************************************************************
* *
* FUNCTION : DrawHand (HDC, int, HPEN, int, int) *
* *
* PURPOSE : Draws a thin hand with the specified pen in the specified *
* hand position. *
* *
***************************************************************************/
DrawHand(hDC, pos, hPen, scale, patMode)
HDC hDC; /* device context to be used when drawing hand */
int pos; /* hand position index into the circle table */
HPEN hPen; /* pen to be used when drawing hand */
int scale; /* ClockRadius percentage to scale drawing to */
int patMode; /* pattern mode to be used when drawing hand */
{
long radius;
/* scale length of hand */
radius = (ClockRadius * scale) / 100;
/* set pattern mode for hand */
SetROP2(hDC, patMode);
/* select pen for hand */
SelectObject(hDC, hPen);
/* Draw thin hand */
MoveTo(hDC, ClockCenter.x, ClockCenter.y);
LineTo(hDC, ClockCenter.x + (int)((lpCirTab[pos].x * radius) / CIRTABSCALE)
ClockCenter.y + (int)((lpCirTab[pos].y * radius) / CIRTABSCALE));
}
/***************************************************************************
* *
* FUNCTION : DrawFatHand (HDC, int, HPEN, BOOL) *
* *
* PURPOSE : Draws a fat hand with the specified pen in the specified *
* hand position. *
* *
***************************************************************************/
DrawFatHand(hDC, pos, hPen, hHand)
HDC hDC; /* device context to be used when drawing hand */
int pos; /* hand position index into the circle table */
HPEN hPen; /* pen to be used when drawing hand */
BOOL hHand; /* TRUE if drawing hour hand; FALSE otherwise */
{
POINT ptTip; /* coordinates for the tip of the hand */
POINT ptTail; /* coordinates for the tail of the hand */
POINT ptSide; /* coordinates for the side of the hand */
int index; /* position index into the circle table */
long scale; /* ClockRadius percentage to scale drawing to */
/* set pattern mode for hand */
SetROP2(hDC, 13);
/* select pen for hand */
SelectObject(hDC, hPen);
/* compute coordinates for the side of the hand */
scale = (ClockRadius * (hHand ? HOURSIDE : MINUTESIDE)) / 100;
index = (pos + SIDESHIFT) % HANDPOSITIONS;
ptSide.y = (lpCirTab[index].y * scale) / CIRTABSCALE;
ptSide.x = (lpCirTab[index].x * scale) / CIRTABSCALE;
/* compute coordinates for the tip of the hand */
scale = (ClockRadius * (hHand ? HOURTIP : MINUTETIP)) / 100;
ptTip.y = (lpCirTab[pos].y * scale) / CIRTABSCALE;
ptTip.x = (lpCirTab[pos].x * scale) / CIRTABSCALE;
/* compute coordinates for the tail of the hand */
scale = (ClockRadius * (hHand ? HOURTAIL : MINUTETAIL)) / 100;
index = (pos + TAILSHIFT) % HANDPOSITIONS;
ptTail.y = (lpCirTab[index].y * scale) / CIRTABSCALE;
ptTail.x = (lpCirTab[index].x * scale) / CIRTABSCALE;
/* Draw tip of hand */
MoveTo(hDC, ClockCenter.x + ptSide.x, ClockCenter.y + ptSide.y);
LineTo(hDC, ClockCenter.x + ptTip.x, ClockCenter.y + ptTip.y);
MoveTo(hDC, ClockCenter.x - ptSide.x, ClockCenter.y - ptSide.y);
LineTo(hDC, ClockCenter.x + ptTip.x, ClockCenter.y + ptTip.y);
/* Draw tail of hand */
MoveTo(hDC, ClockCenter.x + ptSide.x, ClockCenter.y + ptSide.y);
LineTo(hDC, ClockCenter.x + ptTail.x, ClockCenter.y + ptTail.y);
MoveTo(hDC, ClockCenter.x - ptSide.x, ClockCenter.y - ptSide.y);
LineTo(hDC, ClockCenter.x + ptTail.x, ClockCenter.y + ptTail.y);
}
/***************************************************************************
* *
* FUNCTION : CircleClock (int, int) *
* *
* PURPOSE : Resizes the clock rectangle to keep the face circular. *
* *
***************************************************************************/
CircleClock(maxWidth, maxHeight)
int maxWidth; /* the maximum width of the clock face */
int maxHeight; /* the maximum height of the clock face */
{
int clockHeight; /* tallest height that will keep face circular */
int clockWidth; /* widest width that will keep face circular */
if (maxWidth > HorzEquiv(maxHeight))
{
/* too wide -- decrease width to keep face circular */
clockWidth = HorzEquiv(maxHeight);
ClockRect.left += (maxWidth - clockWidth) >> 1;
ClockRect.right = ClockRect.left + clockWidth;
}
else
{
/* too tall -- decrease height to keep face circular */
clockHeight = VertEquiv(maxWidth);
ClockRect.top += (maxHeight - clockHeight) >> 1;
ClockRect.bottom = ClockRect.top + clockHeight;
}
}
/***************************************************************************
* *
* FUNCTION : WinMain (HANDLE, HANDLE, LPSTR, int) *
* *
* PURPOSE : Calls the initialization function, creates the main appli- *
* cation window, and enters the message loop. *
* *
***************************************************************************/
int PASCAL WinMain(hInstance, hPrev, lpszCmdLine, cmdShow)
HANDLE hInstance;
HANDLE hPrev;
LPSTR lpszCmdLine;
int cmdShow;
{
HWND hWnd;
MSG msg;
HMENU hMenu;
TIME nTime;
int sysWidth; /* width of left and right frames */
int sysHeight; /* height of caption bar and top and bottom frames */
int width; /* width of entire clock window */
int height; /* height of entire clock window */
hInst = hInstance;
LoadString(hInst, IDS_APPNAME, (LPSTR) szBuffer, BUFLEN);
if (!hPrev)
{
/* First instance -- register window class */
if (!ClockInit())
return(FALSE);
}
else
{
/* Not first instance -- get circle table and reset bFirst flag */
GetInstanceData(hPrev, (PSTR) &hCirTab, sizeof(HANDLE));
bFirst = FALSE;
}
ClockCreate();
/* compute window height and width */
sysWidth = GetSystemMetrics(SM_CXFRAME) * 2;
sysHeight = GetSystemMetrics(SM_CYCAPTION) + (GetSystemMetrics(SM_CYFRAME)
width = (HorzRes / 3) + sysWidth;
height = VertEquiv(width) + sysHeight;
hWnd = CreateWindow( (LPSTR) szBuffer, /* class name */
(LPSTR) szBuffer, /* The window name */
WS_TILEDWINDOW, /* window style */
CW_USEDEFAULT, /* use default positioning */
0, /* y not used */
width, /* window width */
height, /* window height */
NULL, /* NULL parent handle */
NULL, /* NULL menu/child handle */
hInst, /* program instance */
NULL /* NULL data structure ref.*/
);
GetTime(&nTime);
GetTime(&oTime);
while ((nTime.second == oTime.second) &&
(nTime.minute == oTime.minute) &&
(nTime.hour == oTime.hour) )
{
GetTime(&oTime);
}
if (!SetTimer(hWnd, TimerID, OPEN_TLEN, 0L))
{
LPSTR szTooMany;
/* 16 public timers already in use -- post error and exit */
szTooMany = (LPSTR)(unsigned long) LocalAlloc(LPTR, 40);
LoadString(hInst, IDS_TOOMANY, szTooMany, 40);
MessageBox((HWND) NULL, szTooMany, (LPSTR) szBuffer,
MB_OK | MB_ICONHAND | MB_SYSTEMMODAL);
DeleteTools();
return(FALSE);
}
/* Add the "About..." menu item to the bottom of the system menu */
LoadString(hInst, IDS_ABOUTMENU, (LPSTR) szBuffer, BUFLEN);
hMenu = GetSystemMenu(hWnd, FALSE);
ChangeMenu(hMenu, 0, (LPSTR) szBuffer, IDM_ABOUT, MF_APPEND | MF_STRING);
ShowWindow(hWnd, cmdShow);
/* Process messages until program termination */
while (GetMessage((LPMSG) &msg, NULL, 0, 0))
{
TranslateMessage((LPMSG) &msg);
DispatchMessage((LPMSG) &msg);
}
return(msg.wParam);
}
/***************************************************************************
* *
* FUNCTION : ClockInit () *
* *
* PURPOSE : Registers the applicatoin windwo class and initializes the *
* circle values for the clock face. *
* *
***************************************************************************/
ClockInit()
{
PWNDCLASS pClockClass;
HANDLE hRes;
char szData[5];
pClockClass = (PWNDCLASS) LocalAlloc(LPTR, sizeof(WNDCLASS));
pClockClass->lpszClassName = (LPSTR) szBuffer;
pClockClass->hbrBackground = (HBRUSH) NULL;
pClockClass->style = CS_VREDRAW | CS_HREDRAW | CS_BYTEALIGNCLIENT;
pClockClass->hInstance = hInst;
pClockClass->lpfnWndProc = ClockWndProc;
pClockClass->hCursor = LoadCursor(NULL, IDC_ARROW);
pClockClass->hIcon = NULL;
if (!RegisterClass((LPWNDCLASS) pClockClass))
{
/* Error registering class -- return */
return(FALSE);
}
LocalFree((HANDLE) pClockClass);
/* Load in pre-computed circle table cosine values from resource file */
LoadString(hInst, IDS_DATA, (LPSTR) szData, 5);
hRes = FindResource(hInst, (LPSTR) szBuffer, (LPSTR) szData);
if (!hRes)
{
/* Could not find circle table resource data -- return */
return(FALSE);
}
hCirTab = LoadResource(hInst, hRes);
LockResource(hCirTab);
return(TRUE);
}
CURSOR.C
CD-ROM Disc Path: \SAMPCODE\WIN_SDK\CURSOR\CURSOR.C
/****************************************************************************
PROGRAM: Cursor.c
PURPOSE: Demonstrates how to manipulate a cursor and select a region
FUNCTIONS:
WinMain() - calls initialization function, processes message loop
InitApplication() - initializes window data and registers window
InitInstance() - saves instance handle and creates main window
MainWndProc() - processes messages
About() - processes messages for "About" dialog box
sieve() - time consuming function, generates primes
****************************************************************************/
#include "windows.h"
#include "cursor.h"
HANDLE hInst;
char str[255]; /* general-purpose string buffer
HCURSOR hSaveCursor; /* handle to current cursor
HCURSOR hHourGlass; /* handle to hourglass cursor
BOOL bTrack = FALSE; /* TRUE if left button clicked
int OrgX = 0, OrgY = 0; /* original cursor position
int PrevX = 0, PrevY = 0; /* current cursor position
int X = 0, Y = 0; /* last cursor position
RECT Rect; /* selection rectangle
POINT ptCursor; /* x and y coordinates of cursor
int repeat = 1; /* repeat count of keystroke
/****************************************************************************
FUNCTION: WinMain(HANDLE, HANDLE, LPSTR, int)
PURPOSE: calls initialization function, processes message loop
****************************************************************************/
int PASCAL WinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow)
HANDLE hInstance;
HANDLE hPrevInstance;
LPSTR lpCmdLine;
int nCmdShow;
{
MSG msg;
if (!hPrevInstance)
if (!InitApplication(hInstance))
return (FALSE);
if (!InitInstance(hInstance, nCmdShow))
return (FALSE);
MessageBox (
GetFocus ()
, "Use the mouse button in this program for an example of graphics "
"selection, or the <Enter> key for an example of "
"using a special cursor to reflect a program state."
, "Cursor Sample Application"
, MB_ICONASTERISK | MB_OK
);
while (GetMessage(&msg, NULL, NULL, NULL)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (msg.wParam);
}
/****************************************************************************
FUNCTION: InitApplication(HANDLE)
PURPOSE: Initializes window data and registers window class
****************************************************************************/
BOOL InitApplication(hInstance)
HANDLE hInstance;
{
WNDCLASS wc;
wc.style = NULL;
wc.lpfnWndProc = MainWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(hInstance, "bullseye");
wc.hbrBackground = GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = "CursorMenu";
wc.lpszClassName = "CursorWClass";
return (RegisterClass(&wc));
}
/****************************************************************************
FUNCTION: InitInstance(HANDLE, int)
PURPOSE: Saves instance handle and creates main window
****************************************************************************/
BOOL InitInstance(hInstance, nCmdShow)
HANDLE hInstance;
int nCmdShow;
{
HWND hWnd;
hInst = hInstance;
strcpy(str,"");
hHourGlass = LoadCursor(NULL, IDC_WAIT);
hWnd = CreateWindow(
"CursorWClass",
"Cursor Sample Application",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
hInstance,
NULL
);
if (!hWnd)
return (FALSE);
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return (TRUE);
}
/****************************************************************************
FUNCTION: MainWndProc(HWND, unsigned, WORD, LONG)
PURPOSE: Processes messages
MESSAGES:
WM_COMMAND - application menu (About dialog box)
WM_CHAR - ASCII key value received
WM_LBUTTONDOWN - left mouse button
WM_MOUSEMOVE - mouse movement
WM_LBUTTONUP - left button released
WM_KEYDOWN - key pressed
WM_KEYUPS - key released
WM_PAINT - update window
WM_DESTROY - destroy window
COMMENTS:
When the left mouse button is pressed, btrack is set to TRUE so that
the code for WM_MOUSEMOVE will keep track of the mouse and update
the box accordingly. Once the button is released, btrack is set to
FALSE, and the current position is saved. Holding the SHIFT key
while pressing the left button will extend the current box rather
then erasing it and starting a new one.
When an arrow key is pressed, the cursor is repositioned in the
direction of the arrow key. A repeat count is kept so that the
longer the user holds down the arrow key, the faster it will move.
As soon as the key is released, the repeat count is set to 1 for
normal cursor movement.
****************************************************************************/
long FAR PASCAL MainWndProc(hWnd, message, wParam, lParam)
HWND hWnd;
unsigned message;
WORD wParam;
LONG lParam;
{
FARPROC lpProcAbout;
HDC hDC;
switch (message) {
case WM_COMMAND:
if (wParam == IDM_ABOUT) {
lpProcAbout = MakeProcInstance(About, hInst);
DialogBox(hInst,
"AboutBox",
hWnd,
lpProcAbout);
FreeProcInstance(lpProcAbout);
break;
}
else
return (DefWindowProc(hWnd, message, wParam, lParam));
case WM_CHAR:
if (wParam == '\r') {
SetCapture(hWnd);
/* Set the cursor to an hourglass */
hSaveCursor = SetCursor(hHourGlass);
strcpy (str, "Calculating prime numbers...");
InvalidateRect (hWnd, NULL, TRUE);
UpdateWindow (hWnd);
wsprintf(str, "Calculated %d primes. ", sieve());
InvalidateRect (hWnd, NULL, TRUE);
UpdateWindow (hWnd);
SetCursor(hSaveCursor); /* Restores previous cursor
ReleaseCapture();
}
break;
case WM_LBUTTONDOWN:
bTrack = TRUE;
strcpy (str, "");
PrevX = LOWORD(lParam);
PrevY = HIWORD(lParam);
if (!(wParam & MK_SHIFT)) { /* If shift key is not pressed
OrgX = LOWORD(lParam);
OrgY = HIWORD(lParam);
}
InvalidateRect (hWnd, NULL, TRUE);
UpdateWindow (hWnd);
/* Capture all input even if the mouse goes outside of window */
SetCapture(hWnd);
break;
case WM_MOUSEMOVE:
{
RECT rectClient;
int NextX;
int NextY;
if (bTrack) {
NextX = LOWORD(lParam);
NextY = HIWORD(lParam);
/* Do not draw outside the window's client area */
GetClientRect (hWnd, &rectClient);
if (NextX < rectClient.left) {
NextX = rectClient.left;
} else if (NextX >= rectClient.right) {
NextX = rectClient.right - 1;
}
if (NextY < rectClient.top) {
NextY = rectClient.top;
} else if (NextY >= rectClient.bottom) {
NextY = rectClient.bottom - 1;
}
/* If the mouse position has changed, then clear the */
/* previous rectangle and draw the new one. */
if ((NextX != PrevX) || (NextY != PrevY)) {
hDC = GetDC(hWnd);
SetROP2(hDC, R2_NOT); /* Erases the previous
MoveTo(hDC, OrgX, OrgY);
LineTo(hDC, OrgX, PrevY);
LineTo(hDC, PrevX, PrevY);
LineTo(hDC, PrevX, OrgY);
LineTo(hDC, OrgX, OrgY);
/* Get the current mouse position */
PrevX = NextX;
PrevY = NextY;
MoveTo(hDC, OrgX, OrgY); /* Draws the new box
LineTo(hDC, OrgX, PrevY);
LineTo(hDC, PrevX, PrevY);
LineTo(hDC, PrevX, OrgY);
LineTo(hDC, OrgX, OrgY);
ReleaseDC(hWnd, hDC);
}
}
}
break;
case WM_LBUTTONUP:
bTrack = FALSE; /* No longer creating a selection */
ReleaseCapture(); /* Releases hold on mouse input */
X = LOWORD(lParam); /* Saves the current value */
Y = HIWORD(lParam);
break;
case WM_KEYDOWN:
if (wParam != VK_LEFT && wParam != VK_RIGHT
&& wParam != VK_UP && wParam != VK_DOWN)
break;
GetCursorPos(&ptCursor);
/* Convert screen coordinates to client coordinates */
ScreenToClient(hWnd, &ptCursor);
repeat++; /* Increases the repeat rate
switch (wParam) {
/* Adjust cursor position according to which key was pressed. */
case VK_LEFT:
ptCursor.x -= repeat;
break;
case VK_RIGHT:
ptCursor.x += repeat;
break;
case VK_UP:
ptCursor.y -= repeat;
break;
case VK_DOWN:
ptCursor.y += repeat;
break;
}
/* Get the client boundaries */
GetClientRect(hWnd, &Rect);
/* Do not draw outside the window's client area */
if (ptCursor.x >= Rect.right)
ptCursor.x = Rect.right - 1;
else if (ptCursor.x < Rect.left)
ptCursor.x = Rect.left;
if (ptCursor.y >= Rect.bottom)
ptCursor.y = Rect.bottom - 1;
else if (ptCursor.y < Rect.top)
ptCursor.y = Rect.top;
/* Convert the coordinates to screen coordinates */
ClientToScreen(hWnd, &ptCursor);
SetCursorPos(ptCursor.x, ptCursor.y);
break;
case WM_KEYUP:
repeat = 1; /* Clears the repeat count.
break;
case WM_ACTIVATE:
if (!GetSystemMetrics(SM_MOUSEPRESENT)) {
if (!HIWORD(lParam)) {
if (wParam) {
SetCursor(LoadCursor(hInst, "bullseye"));
ptCursor.x = X;
ptCursor.y = Y;
ClientToScreen(hWnd, &ptCursor);
SetCursorPos(ptCursor.x, ptCursor.y);
}
ShowCursor(wParam);
}
}
break;
case WM_PAINT:
{
PAINTSTRUCT ps;
hDC = BeginPaint (hWnd, &ps);
if (OrgX != PrevX || OrgY != PrevY) {
MoveTo(hDC, OrgX, OrgY);
LineTo(hDC, OrgX, PrevY);
LineTo(hDC, PrevX, PrevY);
LineTo(hDC, PrevX, OrgY);
LineTo(hDC, OrgX, OrgY);
}
TextOut (hDC, 1, 1, str, strlen (str));
EndPaint (hWnd, &ps);
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return (DefWindowProc(hWnd, message, wParam, lParam));
}
return (NULL);
}
/****************************************************************************
FUNCTION: About(HWND, unsigned, WORD, LONG)
PURPOSE: Processes messages for "About" dialog box
MESSAGES:
WM_INITDIALOG - initialize dialog box
WM_COMMAND - Input received
****************************************************************************/
BOOL FAR PASCAL About(hDlg, message, wParam, lParam)
HWND hDlg;
unsigned message;
WORD wParam;
LONG lParam;
{
switch (message) {
case WM_INITDIALOG:
return (TRUE);
case WM_COMMAND:
if (wParam == IDOK
|| wParam == IDCANCEL) {
EndDialog(hDlg, TRUE);
return (TRUE);
}
break;
}
return (FALSE);
}
/****************************************************************************
FUNCTION: Sieve()
PURPOSE: Example of time consuming process
COMMENTS:
Sieve of Eratosthenes, BYTE, Volume 8, Number 1, by Jim Gilbreath
and Gary Gilbreath. Code changed to give correct results.
One could return the count, and after restoring the cursor, use
sprintf() to copy the information to a string which could then be
put up in a MessageBox().
****************************************************************************/
NITER 20 /* number of iterations */
#define SIZE 8190
char flags[SIZE+1]={ 0};
sieve() {
int i,k;
int iter, count;
for (iter = 1; iter <= NITER; iter++) { /* Does sieve NITER times */
count = 0;
for (i = 0; i <= SIZE; i++) /* Sets all flags TRUE */
flags[i] = TRUE;
for (i = 2; i <= SIZE; i++) {
if (flags[i] ) { /* Found a prime? */
for (k = i + i; k <= SIZE; k += i)
flags[k] = FALSE; /* Cancelsits multiples */
count++;
}
}
}
return (count);
}
DEFDLG.C
CD-ROM Disc Path: \SAMPCODE\WIN_SDK\DEFPROCS\DEFDLG.C
/*--------------------------------------------------------------------------*
/* */
/* DefDlgProc() - */
/* */
/*--------------------------------------------------------------------------*
LONG FAR PASCAL DefDlgProc(hwnd, message, wParam, lParam)
register HWND hwnd;
register WORD message;
WORD wParam;
LONG lParam;
{
HWND hwndT1;
HWND hwndT2;
int result;
if (!CheckHwnd(hwnd))
return(NULL);
((PDLG)hwnd)->resultWP = 0L;
if (((PDLG)hwnd)->lpfnDlg == NULL ||
!(result = (*((PDLG)hwnd)->lpfnDlg)(hwnd, message, wParam, lParam)))
{
switch (message)
{
case WM_ERASEBKGND:
FillWindow(hwnd, hwnd, (HDC)wParam, (HBRUSH)CTLCOLOR_DLG);
return((LONG)TRUE);
case WM_SHOWWINDOW:
/* If hiding the window, save the focus. If showing the window
* by means of a SW_* command and the fEnd bit is set, do not
* pass to DWP so it won't get shown.
*/
if (!wParam && ((PDLG)hwnd)->hwndFocusSave == NULL)
((PDLG)hwnd)->hwndFocusSave = hwndFocus;
else if (LOWORD(lParam) != 0 && ((PDLG)hwnd)->fEnd)
break;
goto CallDWP;
case WM_ACTIVATE:
fDialog = FALSE;
if (wParam)
{
fDialog = TRUE;
if (((PDLG)hwnd)->hwndFocusSave)
{
SetFocus(((PDLG)hwnd)->hwndFocusSave);
/* Set to NULL so we don't reset if we get more than
one activate message. */
((PDLG)hwnd)->hwndFocusSave = NULL;
}
}
else if (hwndFocus && IsChild(hwnd, hwndFocus) &&
((PDLG)hwnd)->hwndFocusSave == NULL)
{
/* Must remember focus if deactivated */
((PDLG)hwnd)->hwndFocusSave = hwndFocus;
}
break;
case WM_SETFOCUS:
if (!((PDLG)hwnd)->fEnd)
/* Don't set the focus if we are ending this dialog box
*/
DlgSetFocus(GetFirstTab(hwnd));
break;
case WM_CLOSE:
/* Make sure cancel button is not disabled before sending the
* IDCANCEL. Note that we need to do this as a message instead
* of directly calling the dlg proc so that any dialog box
* filters get this.
*/
hwndT1 = GetDlgItem(hwnd, IDCANCEL);
if (hwndT1 && TestWF(hwndT1, WFDISABLED))
MessageBeep(0);
else
PostMessage(hwnd, WM_COMMAND, IDCANCEL, 0L);
break;
case WM_NCDESTROY:
fDialog = FALSE; /* clear this flag */
if (!(hwnd->style & DS_LOCALEDIT))
{
if (((PDLG)hwnd)->hData)
{
GlobalUnWire(((PDLG)hwnd)->hData);
ReleaseEditDS(((PDLG)hwnd)->hData);
}
}
/* Delete the user defined font if any */
if (((PDLG)hwnd)->hUserFont)
DeleteObject(((PDLG)hwnd)->hUserFont);
/* Gotta let DefWindowProc do its thing here or we won't
* get all of the little chunks of memory freed for this
* window (szName and rgwScroll).
*/
DefWindowProc(hwnd, message, wParam, lParam);
break;
case DM_SETDEFID:
if (!(((PDLG)hwnd)->fEnd) && (((PDLG)hwnd)->result != wParam))
{
/* Make sure that the new default button has the highlight.
* We need to blow this off if we are ending the dialog box
* because hwnd->result is no longer a default window id but
* rather the return value of the dialog box.
*/
/* Catch the case of setting the defid to null or setting
* the defid to something else when it was initially null.
*/
CheckDefPushButton(hwnd,
(((PDLG)hwnd)->result ?
GetDlgItem(hwnd, ((PDLG)hwnd)->result) :
NULL),
(wParam ? GetDlgItem(hwnd, wParam) : NULL));
((PDLG)hwnd)->result = wParam;
}
return(TRUE);
case DM_GETDEFID:
return(MAKELONG(((PDLG)hwnd)->result, DC_HASDEFID));
/* This message was added so that user defined controls that want
* tab keys can pass the tab off to the next/previous control in the
* dialog box. Without this, all they could do was set the focus
* which didn't do the default button stuff.
*/
case WM_NEXTDLGCTL:
hwndT2 = hwndFocus;
if (LOWORD(lParam))
{
if (hwndT2 == NULL)
hwndT2 = hwnd;
/* wParam contains the hwnd of the ctl to set focus to. */
hwndT1 = (HWND)wParam;
}
else
{
if (hwndT2 == NULL)
{
/* Set focus to the first tab item. */
hwndT1 = GetFirstTab(hwnd);
hwndT2 = hwnd;
}
else
{
/* If window with focus not a dlg ctl, ignore message. */
if (!IsChild(hwnd, hwndT2))
return(TRUE);
/* wParam = TRUE for previous, FALSE for next */
hwndT1 = GetNextDlgTabItem(hwnd, hwndT2, wParam);
}
}
DlgSetFocus(hwndT1);
CheckDefPushButton(hwnd, hwndT2, hwndT1);
return(TRUE);
case WM_LBUTTONDOWN:
case WM_NCLBUTTONDOWN:
hwndT1 = hwndFocus;
if (hwndT1->pcls->lpfnWndProc == ComboBoxCtlWndProc)
/* If user clicks anywhere in dialog box and a combo box (or
* the editcontrol of a combo box) has the focus, then hide
* it's listbox.
*/
SendMessage(hwndT1,CB_SHOWDROPDOWN, FALSE, 0L);
else
if (hwndT1->pcls->lpfnWndProc == EditWndProc &&
hwndT1->hwndParent->pcls->lpfnWndProc==ComboBoxCtlWndProc)
{
SendMessage(hwndT1->hwndParent,CB_SHOWDROPDOWN, FALSE, 0L);
}
/* Always send the message off to DefWndProc */
goto CallDWP;
case WM_GETFONT:
return(((PDLG)hwnd)->hUserFont);
case WM_VKEYTOITEM:
case WM_COMPAREITEM:
case WM_CHARTOITEM:
/* We need to return the 0 the app may have returned for these
* items instead of calling defwindow proc.
*/
return(result);
default:
CallDWP:
return(DefWindowProc(hwnd, message, wParam, lParam));
}
}
/* Must return brush which apps dlgfn returns. */
if (message == WM_CTLCOLOR ||
message == WM_COMPAREITEM ||
message == WM_VKEYTOITEM ||
message == WM_CHARTOITEM)
return(result);
return(((PDLG)hwnd)->resultWP);
}
DEFWND.C
CD-ROM Disc Path: \SAMPCODE\WIN_SDK\DEFPROCS\DEFWND.C
/*--------------------------------------------------------------------------*
/* */
/* DefWindowProc() - */
/* */
/*--------------------------------------------------------------------------*
LONG FAR PASCAL DefWindowProc(hwnd, message, wParam, lParam)
register HWND hwnd;
WORD message;
register WORD wParam;
LONG lParam;
{
int i;
HDC hdc;
PAINTSTRUCT ps;
HICON hIcon;
RECT rc;
HANDLE hCurs;
HBRUSH hbr;
HWND hwndT;
if (!CheckHwnd(hwnd))
return((DWORD)FALSE);
switch (message)
{
case WM_NCACTIVATE:
if (wParam != 0)
SetWF(hwnd, WFFRAMEON);
else
ClrWF(hwnd, WFFRAMEON);
if (TestWF(hwnd, WFVISIBLE) && !TestWF(hwnd, WFNONCPAINT))
{
hdc = GetWindowDC(hwnd);
DrawCaption(hwnd, hdc, TRUE, TestWF(hwnd, WFFRAMEON));
InternalReleaseDC(hdc);
if (TestWF(hwnd,WFMINIMIZED))
RedrawIconTitle(hwnd);
}
return(TRUE);
case WM_NCHITTEST:
return(FindNCHit(hwnd, lParam));
case WM_NCCALCSIZE:
CalcClientRect(hwnd, (LPRECT)lParam);
break;
case WM_NCLBUTTONDOWN:
{
WORD cmd;
RECT rcWindow;
RECT rcCapt;
RECT rcInvert;
RECT rcWindowSave;
cmd = 0;
switch(wParam)
{
case HTZOOM:
case HTREDUCE:
GetWindowRect(hwnd, (LPRECT)&rcWindow);
CopyRect((LPRECT)&rcWindowSave, (LPRECT)&rcWindow);
if (TestWF(hwnd, WFSIZEBOX))
InflateRect((LPRECT)&rcWindow,
-cxSzBorderPlus1, -cySzBorderPlus1);
else
InflateRect((LPRECT)&rcWindow, -cxBorder, -cyBorder);
rcCapt.right = rcWindow.right + cxBorder;
rcCapt.left = rcWindow.right - oemInfo.bmReduce.cx-cxBorder
if (wParam == HTREDUCE)
cmd = SC_MINIMIZE;
else if (TestWF(hwnd, WFMAXIMIZED))
cmd = SC_RESTORE;
else
cmd = SC_MAXIMIZE;
if (wParam == HTREDUCE && TestWF(hwnd, WFMAXBOX))
OffsetRect((LPRECT)&rcCapt, -oemInfo.bmReduce.cx, 0);
rcCapt.top = rcWindow.top;
rcCapt.bottom = rcCapt.top + cyCaption;
CopyRect((LPRECT)&rcInvert, (LPRECT)&rcCapt);
InflateRect((LPRECT)&rcInvert, -cxBorder, -cyBorder);
rcInvert.right += cxBorder;
rcInvert.left += cxBorder;
/* Converting to window coordinates. */
OffsetRect((LPRECT)&rcInvert,
-(rcWindowSave.left + cxBorder),
-(rcWindowSave.top + cyBorder));
/* Wait for the BUTTONUP message and see if cursor is still
* in the Minimize or Maximize box.
*
* NOTE: rcInvert is in window coords, rcCapt is in screen
* coords
*/
if (!DepressTitleButton(hwnd, rcCapt, rcInvert, wParam))
cmd = 0;
break;
default:
if (wParam >= HTSIZEFIRST && wParam <= HTSIZELAST)
/* Change HT into a MV command. */
cmd = SC_SIZE + (wParam - HTSIZEFIRST + MVSIZEFIRST);
}
if (cmd != 0)
{
/* For SysCommands on system menu, don't do if
* menu item is disabled.
*/
if (TestWF(hwnd, WFSYSMENU))
{
/* don't check old app child windows
*/
if (LOWORD(GetExpWinVer(hwnd->hInstance)) >= VER ||
!TestwndChild(hwnd))
{
SetSysMenu(hwnd);
if (GetMenuState(GetSysMenuHandle(hwnd), cmd & 0xFFF0,
MF_BYCOMMAND) & (MF_DISABLED | MF_GRAYED))
break;
}
}
SendMessage(hwnd, WM_SYSCOMMAND, cmd, lParam);
break;
}
/*** FALL THRU ***/
}
case WM_NCMOUSEMOVE:
case WM_NCLBUTTONUP:
case WM_NCLBUTTONDBLCLK:
HandleNCMouseGuys(hwnd, message, wParam, lParam);
break;
case WM_CANCELMODE:
if (hwndCapture == hwnd && pfnSB != NULL)
EndScroll(hwnd, TRUE);
if (fMenu && hwndMenu == hwnd)
EndMenu();
/* If the capture is still set, just release at this point.
* Can put other End* functions in later.
*/
if (hwnd == hwndCapture)
ReleaseCapture();
break;
case WM_NCCREATE:
if (TestWF(hwnd, (WFHSCROLL | WFVSCROLL)))
if (InitPwSB(hwnd) == NULL)
return((LONG)FALSE);
return((LONG)DefSetText(hwnd, ((LPCREATESTRUCT)lParam)->lpszName));
case WM_NCDESTROY:
if (hwnd->hName)
hwnd->hName = TextFree(hwnd->hName);
break;
case WM_NCPAINT:
/* Force the drawing of the menu. */
SetWF(hwnd, WFMENUDRAW);
DrawWindowFrame(hwnd, (HRGN)wParam);
ClrWF(hwnd, WFMENUDRAW);
break;
case WM_SETTEXT:
DefSetText(hwnd, (LPSTR)lParam);
if (TestWF(hwnd, WFVISIBLE))
{
if (TestWF(hwnd,WFMINIMIZED))
{
ShowIconTitle(hwnd,FALSE);
ShowIconTitle(hwnd,TRUE);
}
else if (TestWF(hwnd, WFBORDERMASK) == (BYTE)LOBYTE(WFCAPTION))
{
hdc = GetWindowDC(hwnd);
DrawCaption(hwnd, hdc, FALSE, TestWF(hwnd, WFFRAMEON));
InternalReleaseDC(hdc);
}
}
break;
case WM_GETTEXT:
if (wParam)
{
if (hwnd->hName)
return (DWORD)TextCopy(hwnd->hName,(LPSTR)lParam,wParam);
/* else Null terminate the text buffer since there is no text.
*/
((LPSTR)lParam)[0] = NULL;
}
return (0L);
case WM_GETTEXTLENGTH:
if (hwnd->hName)
return(lstrlen(TextPointer(hwnd->hName)));
/* else */
return(0L);
case WM_CLOSE:
DestroyWindow(hwnd);
break;
case WM_PAINT:
BeginPaint(hwnd, (LPPAINTSTRUCT)&ps);
EndPaint(hwnd, (LPPAINTSTRUCT)&ps);
break;
case WM_PAINTICON:
/* Draw the icon through the window DC if app used own DC. If own D
* is used the mapping mode may not be MM_TEXT.
*/
BeginPaint(hwnd, (LPPAINTSTRUCT)&ps);
if (TestCF(hwnd, CFOWNDC) || TestCF(hwnd, CFCLASSDC))
{
/* If owndc, do the end paint now so that the
* erasebackgrounds/validate regions go through properly. Then
* we get a clean window dc to draw the icon into.
*/
InternalEndPaint(hwnd, (LPPAINTSTRUCT)&ps, TRUE);
hdc = GetWindowDC(hwnd);
}
else
{
hdc = ps.hdc;
}
/* wParam is TRUE to draw icon, FALSE to ignore paint. */
if (wParam)
{
hIcon = (HICON)(PCLS)(hwnd->pcls)->hIcon;
GetClientRect(hwnd, (LPRECT)&rc);
rc.left = (rc.right - rgwSysMet[SM_CXICON]) >> 1;
rc.top = (rc.bottom - rgwSysMet[SM_CYICON]) >> 1;
DrawIcon(hdc, rc.left, rc.top, hIcon);
}
/* Delete the update region. */
if (TestCF(hwnd, CFOWNDC) || TestCF(hwnd, CFCLASSDC))
{
InternalReleaseDC(hdc);
/* ValidateRect(hwnd, NULL); */
}
else
InternalEndPaint(hwnd, (LPPAINTSTRUCT)&ps, TRUE);
break;
case WM_ICONERASEBKGND:
/* Erase the icon through the window DC if app used own DC. If own
* DC is used the mapping mode may not be MM_TEXT.
*/
if (TestCF(hwnd, CFOWNDC) || TestCF(hwnd, CFCLASSDC))
hdc = GetWindowDC(hwnd);
else
hdc = (HDC)wParam;
if (TestWF(hwnd, WFCHILD)) /* for MDI child icons */
{
if ((hbr = GetBackBrush(hwnd->hwndParent)) == NULL)
{
/* No brush, punt. */
goto AbortIconEraseBkGnd;
}
else
goto ICantBelieveIUsedAGoToStatement;
}
if (hbmWallpaper)
{
/* Since desktop bitmaps are done on a wm_paint message (and no
* erasebkgnd), we need to call the paint proc with our dc
*/
PaintDesktop(hdc);
/* SendMessage(hwndDesktop, WM_ERASEBKGND, hdc, 0L);*/
}
else
{
hbr = sysClrObjects.hbrDesktop;
ICantBelieveIUsedAGoToStatement:
FillWindow(hwnd->hwndParent,hwnd,hdc,hbr);
}
AbortIconEraseBkGnd:
if (TestCF(hwnd, CFOWNDC) || TestCF(hwnd, CFCLASSDC))
InternalReleaseDC(hdc);
return((LONG)TRUE);
case WM_ERASEBKGND:
if ((hbr = GetBackBrush(hwnd)) != NULL)
{
FillWindow(hwnd, hwnd, (HDC)wParam, hbr);
return((LONG)TRUE);
}
break;
case WM_QUERYOPEN:
case WM_QUERYENDSESSION:
return((LONG)TRUE);
case WM_SYSCOMMAND:
SysCommand(hwnd, wParam, lParam);
break;
case WM_KEYDOWN:
if (wParam == VK_F10)
fF10Status = TRUE;
break;
case WM_SYSKEYDOWN:
/* Is the ALT key down? */
if (HIWORD(lParam) & SYS_ALTERNATE)
{
/* Toggle the fMenuStatus iff this is NOT a repeat KEYDOWN
* message; Only if the prev key state was 0, then this is the
* first KEYDOWN message and then we consider toggling menu
* status;
*/
if((HIWORD(lParam) & SYS_PREVKEYSTATE) == 0)
{
/* Don't have to lock hwndActive because it's processing this
key. */
if ((wParam == VK_MENU) && (!fMenuStatus))
fMenuStatus = TRUE;
else
fMenuStatus = FALSE;
}
fF10Status = FALSE;
DWP_ProcessVirtKey(wParam);
}
else
{
if (wParam == VK_F10)
fF10Status = TRUE;
else
{
if (wParam == VK_ESCAPE)
{
if(GetKeyState(VK_SHIFT) < 0)
SendMessage(hwnd, WM_SYSCOMMAND,
SC_KEYMENU, (DWORD)MENUSYSMENU);
}
}
}
break;
case WM_KEYUP:
case WM_SYSKEYUP:
/* press and release F10 or ALT.Send this only to top-level windows,
* otherwise MDI gets confused. The fix in which DefMDIChildProc()
* passed up the message was insufficient in the case a child window
* of the MDI child had the focus.
*/
if ((wParam == VK_MENU && (fMenuStatus == TRUE)) ||
(wParam == VK_F10 && fF10Status) )
SendMessage(GetTopLevelWindow(hwnd), WM_SYSCOMMAND, SC_KEYMENU,
(DWORD)0);
fF10Status = fMenuStatus = FALSE;
break;
case WM_SYSCHAR:
/* If syskey is down and we have a char... */
fMenuStatus = FALSE;
if ((HIWORD(lParam) & SYS_ALTERNATE) && wParam)
{
if (wParam == VK_TAB || wParam == VK_ESCAPE)
break;
/* Send ALT-SPACE only to top-level windows. */
if ((wParam == MENUSYSMENU) && (TestwndChild(hwnd)))
SendMessage(hwnd->hwndParent, message, wParam, lParam);
else
SendMessage(hwnd, WM_SYSCOMMAND, SC_KEYMENU, (DWORD)wParam);
}
else
/* Ctrl-Esc produces a WM_SYSCHAR, But should not beep; */
if(wParam != VK_ESCAPE)
MessageBeep(0);
break;
case WM_CHARTOITEM:
case WM_VKEYTOITEM:
/* Do default processing for keystrokes into owner draw
listboxes. */
return(-1);
case WM_ACTIVATE:
if (wParam)
SetFocus(hwnd);
break;
case WM_SETREDRAW:
DWP_SetRedraw(hwnd, wParam);
break;
case WM_SHOWWINDOW:
/* Non null descriptor implies popup hide or show. */
/* We should check whether it is a popup window or Owned window */
if (LOWORD(lParam) != 0 && (TestwndPopup(hwnd) || hwnd -> hwndOwner))
{
/* IF NOT(showing, invisible, and not set as hidden) AND
* NOT(hiding and not visible)
*/
if (!(wParam != 0 && !TestWF(hwnd, WFVISIBLE) &&
!TestWF(hwnd, WFHIDDENPOPUP)) &&
!(wParam == 0 && !TestWF(hwnd, WFVISIBLE)))
{
/* Are we showing? */
if (wParam)
/* Yes, clear the hidden popup flag. */
ClrWF(hwnd, WFHIDDENPOPUP);
else
/* No, Set the hidden popup flag. */
SetWF(hwnd, WFHIDDENPOPUP);
ShowWindow(hwnd,
(wParam ? SHOW_OPENNOACTIVATE : HIDE_WINDOW));
}
}
break;
case WM_CTLCOLOR:
if (HIWORD(lParam) != CTLCOLOR_SCROLLBAR)
{
SetBkColor((HDC)wParam, sysColors.clrWindow);
SetTextColor((HDC)wParam, sysColors.clrWindowText);
hbr = sysClrObjects.hbrWindow;
}
else
{
SetBkColor((HDC)wParam, 0x00ffffff);
SetTextColor((HDC)wParam, (LONG)0x00000000);
hbr = sysClrObjects.hbrScrollbar;
UnrealizeObject(hbr);
}
return((DWORD)hbr);
case WM_SETCURSOR:
/* wParam == hwnd that cursor is over
* lParamL == Hit test area code (result of WM_NCHITTEST)
* lParamH == Mouse message number
*/
if (HIWORD(lParam) != 0 &&
LOWORD(lParam) >= HTSIZEFIRST &&
LOWORD(lParam) <= HTSIZELAST)
{
SetCursor(rghCursor[LOWORD(lParam) - HTSIZEFIRST + MVSIZEFIRST]);
break;
}
if ((hwndT = GetChildParent(hwnd)) != NULL &&
(BOOL)SendMessage(hwndT, WM_SETCURSOR, wParam, lParam))
return((LONG)TRUE);
if (HIWORD(lParam) == 0)
{
hCurs = hCursNormal;
SetCursor(hCurs);
}
else
{
switch (LOWORD(lParam))
{
case HTCLIENT:
if (((HWND)wParam)->pcls->hCursor != NULL)
SetCursor(((HWND)wParam)->pcls->hCursor);
break;
case HTERROR:
switch (HIWORD(lParam))
{
case WM_LBUTTONDOWN:
if ((hwndT = DWP_GetEnabledPopup(hwnd)) != NULL)
{
if (hwndT != hwndDesktop->hwndChild)
{
SetWindowPos(hwnd, NULL,
0, 0, 0, 0,
SWP_NOMOVE | SWP_NOSIZE |
SWP_NOACTIVATE);
SetActiveWindow(hwndT);
break;
}
}
/*** FALL THRU ***/
case WM_RBUTTONDOWN:
case WM_MBUTTONDOWN:
MessageBeep(0);
break;
}
/*** FALL THRU ***/
default:
SetCursor(hCursNormal);
}
}
return((LONG)FALSE);
case WM_MOUSEACTIVATE:
if ((hwndT = GetChildParent(hwnd)) != NULL &&
(i = (int)SendMessage(hwndT, WM_MOUSEACTIVATE, wParam, lParam))
!= 0)
return((LONG)i);
/* Moving, sizing or minimizing? Activate AFTER we take action. */
if (LOWORD(lParam) == HTCAPTION)
return((LONG)MA_NOACTIVATE);
else
return((LONG)MA_ACTIVATE);
case WM_DRAWITEM:
if (((LPDRAWITEMSTRUCT)lParam)->CtlType == ODT_LISTBOX)
LBDefaultListboxDrawItem((LPDRAWITEMSTRUCT)lParam);
break;
}
return(0L);
}
DEMO.C
CD-ROM Disc Path: \SAMPCODE\WIN_SDK\SELECT\DEMO.C
/****************************************************************************
PROGRAM: Demo.c
PURPOSE: Demonstrates how to manipulate a cursor and select a region
FUNCTIONS:
WinMain() - calls initialization function, processes message loop
DemoInit() - initializes window data and registers window
DemoWndProc() - processes messages
About() - processes messages for "About" dialog box
COMMENTS:
This code is a modified version of the CURSOR.C program. Instead of
using inline code for drawing the shape, the routines from the Select
library are called.
****************************************************************************/
#include "windows.h"
#include "demo.h"
#include "select.h"
HANDLE hInst;
BOOL bTrack = FALSE;
int OrgX = 0, OrgY = 0;
int PrevX = 0, PrevY = 0;
int X = 0, Y = 0;
RECT Rect;
int Shape = SL_BLOCK; /* Shape to use for rectangle */
BOOL RetainShape = FALSE; /* Retain or destroy shape */
int PASCAL WinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow)
HANDLE hInstance;
HANDLE hPrevInstance;
LPSTR lpCmdLine;
int nCmdShow;
{
HWND hWnd;
MSG msg;
if (!hPrevInstance)
if (!DemoInit(hInstance))
return (NULL);
hInst = hInstance;
hWnd = CreateWindow("Demo",
"Demo Sample Application",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
hInstance,
NULL);
if (!hWnd)
return (NULL);
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
while (GetMessage(&msg, NULL, NULL, NULL)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (msg.wParam);
}
/****************************************************************************
FUNCTION: DemoInit(HANDLE)
PURPOSE: Initializes window data and registers window class
****************************************************************************/
BOOL DemoInit(hInstance)
HANDLE hInstance;
{
HANDLE hMemory;
PWNDCLASS pWndClass;
BOOL bSuccess;
hMemory = LocalAlloc(LPTR, sizeof(WNDCLASS));
pWndClass = (PWNDCLASS) LocalLock(hMemory);
pWndClass->hCursor = LoadCursor(NULL, IDC_ARROW);
pWndClass->hIcon = LoadIcon(NULL, IDI_APPLICATION);
pWndClass->lpszMenuName = (LPSTR) "Menu";
pWndClass->lpszClassName = (LPSTR) "Demo";
pWndClass->hbrBackground = GetStockObject(WHITE_BRUSH);
pWndClass->hInstance = hInstance;
pWndClass->style = NULL;
pWndClass->lpfnWndProc = DemoWndProc;
bSuccess = RegisterClass(pWndClass);
LocalUnlock(hMemory);
LocalFree(hMemory);
return (bSuccess);
}
/****************************************************************************
FUNCTION: DemoWndProc(HWND, unsigned, WORD, LONG)
PURPOSE: Processes messages
MESSAGES:
WM_SYSCOMMAND - system menu (About dialog box)
WM_CREATE - create window
WM_DESTROY - destroy window
WM_LBUTTONDOWN - left mouse button
WM_MOUSEMOVE - mouse movement
WM_LBUTTONUP - left button released
WM_COMMAND messages:
IDM_BOX - use inverted box for selecting a region
IDM_BLOCK - use empty box for selecting a region
IDM_RETAIN - retain/delete selection on button release
COMMENTS:
When the left mouse button is pressed, btrack is set to TRUE so that
the code for WM_MOUSEMOVE will keep track of the mouse and update the
box accordingly. Once the button is released, btrack is set to
FALSE, and the current position is saved. Holding the SHIFT key
while pressing the left button will extend the current box rather
then erasing it and starting a new one. The exception is when the
retain shape option is enabled. With this option, the rectangle is
zeroed whenever the mouse is released so that it can not be erased or
extended.
****************************************************************************/
long FAR PASCAL DemoWndProc(hWnd, message, wParam, lParam)
HWND hWnd;
unsigned message;
WORD wParam;
LONG lParam;
{
FARPROC lpProcAbout;
HMENU hMenu;
switch (message) {
case WM_COMMAND:
switch (wParam) {
case IDM_BOX:
Shape = SL_BOX;
hMenu = GetMenu(hWnd);
CheckMenuItem(hMenu, IDM_BOX, MF_CHECKED);
CheckMenuItem(hMenu, IDM_BLOCK, MF_UNCHECKED);
break;
case IDM_BLOCK:
Shape = SL_BLOCK;
hMenu = GetMenu(hWnd);
CheckMenuItem(hMenu, IDM_BOX, MF_UNCHECKED);
CheckMenuItem(hMenu, IDM_BLOCK, MF_CHECKED);
break;
case IDM_RETAIN:
if (RetainShape) {
hMenu = GetMenu(hWnd);
CheckMenuItem(hMenu, IDM_RETAIN, MF_UNCHECKED);
RetainShape = FALSE;
}
else {
hMenu = GetMenu(hWnd);
CheckMenuItem(hMenu, IDM_RETAIN, MF_CHECKED);
RetainShape = TRUE;
}
break;
case IDM_ABOUT:
lpProcAbout = MakeProcInstance(About, hInst);
DialogBox(hInst, "AboutBox", hWnd, lpProcAbout);
FreeProcInstance(lpProcAbout);
break;
}
break;
case WM_LBUTTONDOWN:
bTrack = TRUE; /* user has pressed the left button */
/* If you don't want the shape cleared, you must clear the Rect
* coordinates before calling StartSelection
*/
if (RetainShape)
SetRectEmpty(&Rect);
StartSelection(hWnd, MAKEPOINT(lParam), &Rect,
(wParam & MK_SHIFT) ? SL_EXTEND | Shape : Shape);
break;
case WM_MOUSEMOVE:
if (bTrack)
UpdateSelection(hWnd, MAKEPOINT(lParam), &Rect, Shape);
break;
case WM_LBUTTONUP:
if (bTrack)
EndSelection(MAKEPOINT(lParam), &Rect);
bTrack = FALSE;
break;
case WM_SIZE:
switch (wParam) {
case SIZEICONIC:
/* If we aren't in retain mode we want to clear the
* current rectangle now!
*/
if (!RetainShape)
SetRectEmpty(&Rect);
}
break;
case WM_DESTROY:
PostQuitMessage(NULL);
break;
default:
return (DefWindowProc(hWnd, message, wParam, lParam));
}
return (NULL);
}
/****************************************************************************
FUNCTION: About(HWND, unsigned, WORD, LONG)
PURPOSE: Processes messages for "About" dialog box
MESSAGES:
WM_INITDIALOG - initialize dialog box
WM_COMMAND - Input received
****************************************************************************/
BOOL FAR PASCAL About(hDlg, message, wParam, lParam)
HWND hDlg;
unsigned message;
WORD wParam;
LONG lParam;
{
switch (message) {
case WM_INITDIALOG:
return (TRUE);
case WM_COMMAND:
if (wParam == IDOK
|| wParam == IDCANCEL) {
EndDialog(hDlg, TRUE);
return (TRUE);
}
return (TRUE);
}
return (FALSE);
}
DIB.C
CD-ROM Disc Path: \SAMPCODE\WIN_SDK\SHOWDIB\DIB.C
/****************************************************************************
* *
* MODULE : DIB.C *
* *
* DESCRIPTION : Routines for dealing with Device Independent Bitmaps.
* *
* FUNCTIONS : OpenDIB() - Opens DIB file and creates a memory DIB*
* *
* WriteDIB() - Writes a global handle in CF_DIB format*
* to a file. *
* *
* DibInfo() - Retrieves the info. block associated *
* with a CF_DIB format memory block. *
* *
* CreateBIPalette() - Creates a GDI palette given a pointer *
* to a BITMAPINFO structure. *
* *
* CreateDibPalette() - Creates a GDI palette given a HANDLE *
* to a BITMAPINFO structure. *
* *
* ReadDibBitmapInfo() - Reads a file in DIB format and returns *
* a global handle to it's BITMAPINFO *
* *
* PaletteSize() - Calculates the palette size in bytes *
* of given DIB *
* *
* DibNumColors() - Determines the number of colors in DIB *
* *
* BitmapFromDib() - Creates a DDB given a global handle to *
* a block in CF_DIB format. *
* *
* DibFromBitmap() - Creates a DIB repr. the DDB passed in. *
* *
* DrawBitmap() - Draws a bitmap at specified position *
* in the DC. *
* *
* DibBlt() - Draws a bitmap in CIF_DIB format using *
* SetDIBitsToDevice() *
* *
* StretchDibBlt() - Draws a bitmap in CIF_DIB format using *
* StretchDIBits() *
* *
* lread() - Private routine to read more than 64k *
* *
* lwrite() - Private routine to write more than 64k *
* *
****************************************************************************
#include <windows.h>
#include "showdib.h"
static HCURSOR hcurSave;
/****************************************************************************
* *
* FUNCTION :OpenDIB(LPSTR szFile) *
* *
* PURPOSE :Open a DIB file and create a MEMORY DIB, a memory handle *
* containing BITMAPINFO, palette data and the bits. *
* *
* RETURNS :A handle to the DIB. *
* *
****************************************************************************
HANDLE OpenDIB (szFile)
LPSTR szFile;
{
unsigned fh;
BITMAPINFOHEADER bi;
LPBITMAPINFOHEADER lpbi;
DWORD dwLen = 0;
DWORD dwBits;
HANDLE hdib;
HANDLE h;
OFSTRUCT of;
/* Open the file and read the DIB information */
fh = OpenFile(szFile, &of, OF_READ);
if (fh == -1)
return NULL;
hdib = ReadDibBitmapInfo(fh);
if (!hdib)
return NULL;
DibInfo(hdib,&bi);
/* Calculate the memory needed to hold the DIB */
dwBits = bi.biSizeImage;
dwLen = bi.biSize + (DWORD)PaletteSize (&bi) + dwBits;
/* Try to increase the size of the bitmap info. buffer to hold the DIB */
h = GlobalReAlloc(hdib, dwLen, GHND);
if (!h){
GlobalFree(hdib);
hdib = NULL;
}
else
hdib = h;
/* Read in the bits */
if (hdib){
lpbi = (VOID FAR *)GlobalLock(hdib);
lread(fh, (LPSTR)lpbi + (WORD)lpbi->biSize + PaletteSize(lpbi), dwBits);
GlobalUnlock(hdib);
}
_lclose(fh);
return hdib;
}
/****************************************************************************
* *
* FUNCTION : WriteDIB(LPSTR szFile,HANDLE hdib) *
* *
* PURPOSE : Write a global handle in CF_DIB format to a file. *
* *
* RETURNS : TRUE - if successful. *
* FALSE - otherwise *
* *
****************************************************************************
BOOL WriteDIB (szFile, hdib)
LPSTR szFile;
HANDLE hdib;
{
BITMAPFILEHEADER hdr;
LPBITMAPINFOHEADER lpbi;
int fh;
OFSTRUCT of;
if (!hdib)
return FALSE;
fh = OpenFile (szFile, &of, OF_CREATE|OF_READWRITE);
if (fh == -1)
return FALSE;
lpbi = (VOID FAR *)GlobalLock (hdib);
/* Fill in the fields of the file header */
hdr.bfType = BFT_BITMAP;
hdr.bfSize = GlobalSize (hdib) + sizeof (BITMAPFILEHEADER);
hdr.bfReserved1 = 0;
hdr.bfReserved2 = 0;
hdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + lpbi->biSize +
PaletteSize(lpbi);
/* Write the file header */
_lwrite (fh, (LPSTR)&hdr, sizeof (BITMAPFILEHEADER));
/* Write the DIB header and the bits */
lwrite (fh, (LPSTR)lpbi, GlobalSize (hdib));
GlobalUnlock (hdib);
_lclose (fh);
return TRUE;
}
/****************************************************************************
* *
* FUNCTION : DibInfo(HANDLE hbi,LPBITMAPINFOHEADER lpbi) *
* *
* PURPOSE : Retrieves the DIB info associated with a CF_DIB *
* format memory block. *
* *
* RETURNS : TRUE - if successful. *
* FALSE - otherwise *
* *
****************************************************************************
BOOL DibInfo (hbi, lpbi)
HANDLE hbi;
LPBITMAPINFOHEADER lpbi;
{
if (hbi){
*lpbi = *(LPBITMAPINFOHEADER)GlobalLock (hbi);
/* fill in the default fields */
if (lpbi->biSize != sizeof (BITMAPCOREHEADER)){
if (lpbi->biSizeImage == 0L)
lpbi->biSizeImage =
WIDTHBYTES(lpbi->biWidth*lpbi->biBitCount) * lpbi->biHeight;
if (lpbi->biClrUsed == 0L)
lpbi->biClrUsed = DibNumColors (lpbi);
}
GlobalUnlock (hbi);
return TRUE;
}
return FALSE;
}
/****************************************************************************
* *
* FUNCTION : CreateBIPalette(LPBITMAPINFOHEADER lpbi) *
* *
* PURPOSE : Given a Pointer to a BITMAPINFO struct will create a *
* a GDI palette object from the color table. *
* *
* RETURNS : A handle to the palette. *
* *
****************************************************************************
HPALETTE CreateBIPalette (lpbi)
LPBITMAPINFOHEADER lpbi;
{
LOGPALETTE *pPal;
HPALETTE hpal = NULL;
WORD nNumColors;
BYTE red;
BYTE green;
BYTE blue;
int i;
RGBQUAD FAR *pRgb;
if (!lpbi)
return NULL;
if (lpbi->biSize != sizeof(BITMAPINFOHEADER))
return NULL;
/* Get a pointer to the color table and the number of colors in it */
pRgb = (RGBQUAD FAR *)((LPSTR)lpbi + (WORD)lpbi->biSize);
nNumColors = DibNumColors(lpbi);
if (nNumColors){
/* Allocate for the logical palette structure */
pPal = (LOGPALETTE*)LocalAlloc(LPTR,sizeof(LOGPALETTE) + nNumColors *
if (!pPal)
return NULL;
pPal->palNumEntries = nNumColors;
pPal->palVersion = PALVERSION;
/* Fill in the palette entries from the DIB color table and
* create a logical color palette.
*/
for (i = 0; i < nNumColors; i++){
pPal->palPalEntry[i].peRed = pRgb[i].rgbRed;
pPal->palPalEntry[i].peGreen = pRgb[i].rgbGreen;
pPal->palPalEntry[i].peBlue = pRgb[i].rgbBlue;
pPal->palPalEntry[i].peFlags = (BYTE)0;
}
hpal = CreatePalette(pPal);
LocalFree((HANDLE)pPal);
}
else if (lpbi->biBitCount == 24){
/* A 24 bitcount DIB has no color table entries so, set the number of
* to the maximum value (256).
*/
nNumColors = MAXPALETTE;
pPal = (LOGPALETTE*)LocalAlloc(LPTR,sizeof(LOGPALETTE) + nNumColors *
if (!pPal)
return NULL;
pPal->palNumEntries = nNumColors;
pPal->palVersion = PALVERSION;
red = green = blue = 0;
/* Generate 256 (= 8*8*4) RGB combinations to fill the palette
* entries.
*/
for (i = 0; i < pPal->palNumEntries; i++){
pPal->palPalEntry[i].peRed = red;
pPal->palPalEntry[i].peGreen = green;
pPal->palPalEntry[i].peBlue = blue;
pPal->palPalEntry[i].peFlags = (BYTE)0;
if (!(red += 32))
if (!(green += 32))
blue += 64;
}
hpal = CreatePalette(pPal);
LocalFree((HANDLE)pPal);
}
return hpal;
}
/****************************************************************************
* *
* FUNCTION : CreateDibPalette(HANDLE hbi) *
* *
* PURPOSE : Given a Global HANDLE to a BITMAPINFO Struct *
* will create a GDI palette object from the color table. *
* (BITMAPINFOHEADER format DIBs only) *
* *
* RETURNS : A handle to the palette. *
* *
****************************************************************************
HPALETTE CreateDibPalette (hbi)
HANDLE hbi;
{
HPALETTE hpal;
if (!hbi)
return NULL;
hpal = CreateBIPalette((LPBITMAPINFOHEADER)GlobalLock(hbi));
GlobalUnlock(hbi);
return hpal;
}
/****************************************************************************
* *
* FUNCTION : ReadDibBitmapInfo(int fh) *
* *
* PURPOSE : Will read a file in DIB format and return a global HANDLE *
* to it's BITMAPINFO. This function will work with both *
* "old" (BITMAPCOREHEADER) and "new" (BITMAPINFOHEADER) *
* bitmap formats, but will always return a "new" BITMAPINFO *
* *
* RETURNS : A handle to the BITMAPINFO of the DIB in the file. *
* *
****************************************************************************
HANDLE ReadDibBitmapInfo (fh)
int fh;
{
DWORD off;
HANDLE hbi = NULL;
int size;
int i;
WORD nNumColors;
RGBQUAD FAR *pRgb;
BITMAPINFOHEADER bi;
BITMAPCOREHEADER bc;
LPBITMAPINFOHEADER lpbi;
BITMAPFILEHEADER bf;
DWORD dwWidth = 0;
DWORD dwHeight = 0;
WORD wPlanes, wBitCount;
if (fh == -1)
return NULL;
/* Reset file pointer and read file header */
off = _llseek(fh, 0L, SEEK_CUR);
if (sizeof (bf) != _lread (fh, (LPSTR)&bf, sizeof (bf)))
return FALSE;
/* Do we have a RC HEADER? */
if (!ISDIB (bf.bfType)) {
bf.bfOffBits = 0L;
_llseek (fh, off, SEEK_SET);
}
if (sizeof (bi) != _lread (fh, (LPSTR)&bi, sizeof(bi)))
return FALSE;
nNumColors = DibNumColors (&bi);
/* Check the nature (BITMAPINFO or BITMAPCORE) of the info. block
* and extract the field information accordingly. If a BITMAPCOREHEADER,
* transfer it's field information to a BITMAPINFOHEADER-style block
*/
switch (size = (int)bi.biSize){
case sizeof (BITMAPINFOHEADER):
break;
case sizeof (BITMAPCOREHEADER):
bc = *(BITMAPCOREHEADER*)&bi;
dwWidth = (DWORD)bc.bcWidth;
dwHeight = (DWORD)bc.bcHeight;
wPlanes = bc.bcPlanes;
wBitCount = bc.bcBitCount;
bi.biSize = sizeof(BITMAPINFOHEADER);
bi.biWidth = dwWidth;
bi.biHeight = dwHeight;
bi.biPlanes = wPlanes;
bi.biBitCount = wBitCount;
bi.biCompression = BI_RGB;
bi.biSizeImage = 0;
bi.biXPelsPerMeter = 0;
bi.biYPelsPerMeter = 0;
bi.biClrUsed = nNumColors;
bi.biClrImportant = nNumColors;
_llseek (fh, (LONG)sizeof (BITMAPCOREHEADER) - sizeof (BITMAPINFOHEADER
break;
default:
/* Not a DIB! */
return NULL;
}
/* Fill in some default values if they are zero */
if (bi.biSizeImage == 0){
bi.biSizeImage = WIDTHBYTES ((DWORD)bi.biWidth * bi.biBitCount)
* bi.biHeight;
}
if (bi.biClrUsed == 0)
bi.biClrUsed = DibNumColors(&bi);
/* Allocate for the BITMAPINFO structure and the color table. */
hbi = GlobalAlloc (GHND, (LONG)bi.biSize + nNumColors * sizeof(RGBQUAD));
if (!hbi)
return NULL;
lpbi = (VOID FAR *)GlobalLock (hbi);
*lpbi = bi;
/* Get a pointer to the color table */
pRgb = (RGBQUAD FAR *)((LPSTR)lpbi + bi.biSize);
if (nNumColors){
if (size == sizeof(BITMAPCOREHEADER)){
/* Convert a old color table (3 byte RGBTRIPLEs) to a new
* color table (4 byte RGBQUADs)
*/
_lread (fh, (LPSTR)pRgb, nNumColors * sizeof(RGBTRIPLE));
for (i = nNumColors - 1; i >= 0; i--){
RGBQUAD rgb;
rgb.rgbRed = ((RGBTRIPLE FAR *)pRgb)[i].rgbtRed;
rgb.rgbBlue = ((RGBTRIPLE FAR *)pRgb)[i].rgbtBlue;
rgb.rgbGreen = ((RGBTRIPLE FAR *)pRgb)[i].rgbtGreen;
rgb.rgbReserved = (BYTE)0;
pRgb[i] = rgb;
}
}
else
_lread(fh,(LPSTR)pRgb,nNumColors * sizeof(RGBQUAD));
}
if (bf.bfOffBits != 0L)
_llseek(fh,off + bf.bfOffBits,SEEK_SET);
GlobalUnlock(hbi);
return hbi;
}
/****************************************************************************
* *
* FUNCTION : PaletteSize(VOID FAR * pv) *
* *
* PURPOSE : Calculates the palette size in bytes. If the info. block *
* is of the BITMAPCOREHEADER type, the number of colors is *
* multiplied by 3 to give the palette size, otherwise the *
* number of colors is multiplied by 4. *
* *
* RETURNS : Palette size in number of bytes. *
* *
****************************************************************************
WORD PaletteSize (pv)
VOID FAR * pv;
{
LPBITMAPINFOHEADER lpbi;
WORD NumColors;
lpbi = (LPBITMAPINFOHEADER)pv;
NumColors = DibNumColors(lpbi);
if (lpbi->biSize == sizeof(BITMAPCOREHEADER))
return NumColors * sizeof(RGBTRIPLE);
else
return NumColors * sizeof(RGBQUAD);
}
/****************************************************************************
* *
* FUNCTION : DibNumColors(VOID FAR * pv) *
* *
* PURPOSE : Determines the number of colors in the DIB by looking at *
* the BitCount filed in the info block. *
* *
* RETURNS : The number of colors in the DIB. *
* *
****************************************************************************
WORD DibNumColors (pv)
VOID FAR * pv;
{
int bits;
LPBITMAPINFOHEADER lpbi;
LPBITMAPCOREHEADER lpbc;
lpbi = ((LPBITMAPINFOHEADER)pv);
lpbc = ((LPBITMAPCOREHEADER)pv);
/* With the BITMAPINFO format headers, the size of the palette
* is in biClrUsed, whereas in the BITMAPCORE - style headers, it
* is dependent on the bits per pixel ( = 2 raised to the power of
* bits/pixel).
*/
if (lpbi->biSize != sizeof(BITMAPCOREHEADER)){
if (lpbi->biClrUsed != 0)
return (WORD)lpbi->biClrUsed;
bits = lpbi->biBitCount;
}
else
bits = lpbc->bcBitCount;
switch (bits){
case 1:
return 2;
case 4:
return 16;
case 8:
return 256;
default:
/* A 24 bitcount DIB has no color table */
return 0;
}
}
/****************************************************************************
* *
* FUNCTION : DibFromBitmap() *
* *
* PURPOSE : Will create a global memory block in DIB format that *
* represents the Device-dependent bitmap (DDB) passed in. *
* *
* RETURNS : A handle to the DIB *
* *
****************************************************************************
HANDLE DibFromBitmap (hbm, biStyle, biBits, hpal)
HBITMAP hbm;
DWORD biStyle;
WORD biBits;
HPALETTE hpal;
{
BITMAP bm;
BITMAPINFOHEADER bi;
BITMAPINFOHEADER FAR *lpbi;
DWORD dwLen;
HANDLE hdib;
HANDLE h;
HDC hdc;
if (!hbm)
return NULL;
if (hpal == NULL)
hpal = GetStockObject(DEFAULT_PALETTE);
GetObject(hbm,sizeof(bm),(LPSTR)&bm);
if (biBits == 0)
biBits = bm.bmPlanes * bm.bmBitsPixel;
bi.biSize = sizeof(BITMAPINFOHEADER);
bi.biWidth = bm.bmWidth;
bi.biHeight = bm.bmHeight;
bi.biPlanes = 1;
bi.biBitCount = biBits;
bi.biCompression = biStyle;
bi.biSizeImage = 0;
bi.biXPelsPerMeter = 0;
bi.biYPelsPerMeter = 0;
bi.biClrUsed = 0;
bi.biClrImportant = 0;
dwLen = bi.biSize + PaletteSize(&bi);
hdc = GetDC(NULL);
hpal = SelectPalette(hdc,hpal,FALSE);
RealizePalette(hdc);
hdib = GlobalAlloc(GHND,dwLen);
if (!hdib){
SelectPalette(hdc,hpal,FALSE);
ReleaseDC(NULL,hdc);
return NULL;
}
lpbi = (VOID FAR *)GlobalLock(hdib);
*lpbi = bi;
/* call GetDIBits with a NULL lpBits param, so it will calculate the
* biSizeImage field for us
*/
GetDIBits(hdc, hbm, 0, (WORD)bi.biHeight,
NULL, (LPBITMAPINFO)lpbi, DIB_RGB_COLORS);
bi = *lpbi;
GlobalUnlock(hdib);
/* If the driver did not fill in the biSizeImage field, make one up */
if (bi.biSizeImage == 0){
bi.biSizeImage = WIDTHBYTES((DWORD)bm.bmWidth * biBits) * bm.bmHeight
if (biStyle != BI_RGB)
bi.biSizeImage = (bi.biSizeImage * 3) / 2;
}
/* realloc the buffer big enough to hold all the bits */
dwLen = bi.biSize + PaletteSize(&bi) + bi.biSizeImage;
if (h = GlobalReAlloc(hdib,dwLen,0))
hdib = h;
else{
GlobalFree(hdib);
hdib = NULL;
SelectPalette(hdc,hpal,FALSE);
ReleaseDC(NULL,hdc);
return hdib;
}
/* call GetDIBits with a NON-NULL lpBits param, and actualy get the
* bits this time
*/
lpbi = (VOID FAR *)GlobalLock(hdib);
if (GetDIBits( hdc,
hbm,
0,
(WORD)bi.biHeight,
(LPSTR)lpbi + (WORD)lpbi->biSize + PaletteSize(lpbi),
(LPBITMAPINFO)lpbi, DIB_RGB_COLORS) == 0){
GlobalUnlock(hdib);
hdib = NULL;
SelectPalette(hdc,hpal,FALSE);
ReleaseDC(NULL,hdc);
return NULL;
}
bi = *lpbi;
GlobalUnlock(hdib);
SelectPalette(hdc,hpal,FALSE);
ReleaseDC(NULL,hdc);
return hdib;
}
/****************************************************************************
* *
* FUNCTION : BitmapFromDib(HANDLE hdib, HPALETTE hpal) *
* *
* PURPOSE : Will create a DDB (Device Dependent Bitmap) given a global *
* handle to a memory block in CF_DIB format *
* *
* RETURNS : A handle to the DDB. *
* *
****************************************************************************
HBITMAP BitmapFromDib (hdib, hpal)
HANDLE hdib;
HPALETTE hpal;
{
LPBITMAPINFOHEADER lpbi;
HPALETTE hpalT;
HDC hdc;
HBITMAP hbm;
StartWait();
if (!hdib)
return NULL;
lpbi = (VOID FAR *)GlobalLock(hdib);
if (!lpbi)
return NULL;
hdc = GetDC(NULL);
if (hpal){
hpalT = SelectPalette(hdc,hpal,FALSE);
RealizePalette(hdc); // GDI Bug...????
}
hbm = CreateDIBitmap(hdc,
(LPBITMAPINFOHEADER)lpbi,
(LONG)CBM_INIT,
(LPSTR)lpbi + lpbi->biSize + PaletteSize(lpbi),
(LPBITMAPINFO)lpbi,
DIB_RGB_COLORS );
if (hpal)
SelectPalette(hdc,hpalT,FALSE);
ReleaseDC(NULL,hdc);
GlobalUnlock(hdib);
EndWait();
return hbm;
}
/****************************************************************************
* *
* FUNCTION : DrawBitmap(HDC hdc, int x, int y, HBITMAP hbm, DWORD rop) *
* *
* PURPOSE : Draws bitmap <hbm> at the specifed position in DC <hdc> *
* *
* RETURNS : Return value of BitBlt() *
* *
****************************************************************************
BOOL DrawBitmap (hdc, x, y, hbm, rop)
HDC hdc;
int x, y;
HBITMAP hbm;
DWORD rop;
{
HDC hdcBits;
BITMAP bm;
HPALETTE hpalT;
BOOL f;
if (!hdc || !hbm)
return FALSE;
hdcBits = CreateCompatibleDC(hdc);
GetObject(hbm,sizeof(BITMAP),(LPSTR)&bm);
SelectObject(hdcBits,hbm);
f = BitBlt(hdc,0,0,bm.bmWidth,bm.bmHeight,hdcBits,0,0,rop);
DeleteDC(hdcBits);
return f;
}
/****************************************************************************
* *
* FUNCTION : DibBlt( HDC hdc, *
* int x0, int y0, *
* int dx, int dy, *
* HANDLE hdib, *
* int x1, int y1, *
* LONG rop) *
* *
* PURPOSE : Draws a bitmap in CF_DIB format, using SetDIBits to device.*
* taking the same parameters as BitBlt(). *
* *
* RETURNS : TRUE - if function succeeds. *
* FALSE - otherwise. *
* *
****************************************************************************
BOOL DibBlt (hdc, x0, y0, dx, dy, hdib, x1, y1, rop)
HDC hdc;
int x0, y0, dx, dy;
HANDLE hdib;
int x1, y1;
LONG rop;
{
LPBITMAPINFOHEADER lpbi;
HPALETTE hpal,hpalT;
LPSTR pBuf;
HDC hdcMem;
HBITMAP hbm,hbmT;
if (!hdib)
return PatBlt(hdc,x0,y0,dx,dy,rop);
lpbi = (VOID FAR *)GlobalLock(hdib);
if (!lpbi)
return FALSE;
pBuf = (LPSTR)lpbi + (WORD)lpbi->biSize + PaletteSize(lpbi);
SetDIBitsToDevice (hdc, x0, y0, dx, dy,
x1,y1,
x1,
dy,
pBuf, (LPBITMAPINFO)lpbi,
DIB_RGB_COLORS );
GlobalUnlock(hdib);
return TRUE;
}
/****************************************************************************
* *
* FUNCTION : StretchDibBlt( HDC hdc, *
* int x, int y, *
* int dx, int dy, *
* HANDLE hdib, *
* int x0, int y0, *
* int dx0, int dy0, *
* LONG rop) *
* *
* PURPOSE : Draws a bitmap in CF_DIB format, using StretchDIBits() *
* taking the same parameters as StretchBlt(). *
* *
* RETURNS : TRUE - if function succeeds. *
* FALSE - otherwise. *
* *
****************************************************************************
BOOL StretchDibBlt (hdc, x, y, dx, dy, hdib, x0, y0, dx0, dy0, rop)
HDC hdc;
int x, y;
int dx, dy;
HANDLE hdib;
int x0, y0;
int dx0, dy0;
LONG rop;
{
LPBITMAPINFOHEADER lpbi;
LPSTR pBuf;
BOOL f;
if (!hdib)
return PatBlt(hdc,x,y,dx,dy,rop);
lpbi = (VOID FAR *)GlobalLock(hdib);
if (!lpbi)
return FALSE;
pBuf = (LPSTR)lpbi + (WORD)lpbi->biSize + PaletteSize(lpbi);
f = StretchDIBits ( hdc,
x, y,
dx, dy,
x0, y0,
dx0, dy0,
pBuf, (LPBITMAPINFO)lpbi,
DIB_RGB_COLORS,
rop);
GlobalUnlock(hdib);
return f;
}
/************* PRIVATE ROUTINES TO READ/WRITE MORE THAN 64K ***************/
/****************************************************************************
* *
* FUNCTION : lread(int fh, VOID FAR *pv, DWORD ul) *
* *
* PURPOSE : Reads data in steps of 32k till all the data has been read.*
* *
* RETURNS : 0 - If read did not proceed correctly. *
* number of bytes read otherwise. *
* *
****************************************************************************
DWORD PASCAL lread (fh, pv, ul)
int fh;
VOID far *pv;
DWORD ul;
{
DWORD ulT = ul;
BYTE huge *hp = pv;
while (ul > (DWORD)MAXREAD) {
if (_lread(fh, (LPSTR)hp, (WORD)MAXREAD) != MAXREAD)
return 0;
ul -= MAXREAD;
hp += MAXREAD;
}
if (_lread(fh, (LPSTR)hp, (WORD)ul) != (WORD)ul)
return 0;
return ulT;
}
/****************************************************************************
* *
* FUNCTION : lwrite(int fh, VOID FAR *pv, DWORD ul) *
* *
* PURPOSE : Writes data in steps of 32k till all the data is written. *
* *
* RETURNS : 0 - If write did not proceed correctly. *
* number of bytes written otherwise. *
* *
****************************************************************************
DWORD PASCAL lwrite (fh, pv, ul)
int fh;
VOID FAR *pv;
DWORD ul;
{
DWORD ulT = ul;
BYTE huge *hp = pv;
while (ul > MAXREAD) {
if (_lwrite(fh, (LPSTR)hp, (WORD)MAXREAD) != MAXREAD)
return 0;
ul -= MAXREAD;
hp += MAXREAD;
}
if (_lwrite(fh, (LPSTR)hp, (WORD)ul) != (WORD)ul)
return 0;
return ulT;
}
DLGOPEN.C
CD-ROM Disc Path: \SAMPCODE\WIN_SDK\SHOWDIB\DLGOPEN.C
/****************************************************************************
* *
* MODULE : DLGOPEN.C *
* *
* DESCRIPTION : Routines to display a standard File/Open and File/Save
* dialog boxes. *
* *
* FUNCTIONS : DlgOpenFile() - Displays a dialog box for opening or saving
* file. *
* *
* DlgfnOpen() - Dialog function for the above dialog. *
* *
* AddExt() - Adds an extension to a filename if not *
* already present. *
* *
* FSearchSpec() - Checks if given string contains a wildcard *
* character. *
* *
* FillListBox() - Fills listbox with files that match specs. *
* *
* DlgCheckOkEnable() - Enables <OK> button iff there's text in *
* the edit control. *
* *
* NOTE : These routines require that the app. be running *
* SS = DS since they use near pointers into the stack. *
* *
****************************************************************************
#include <windows.h>
#include "showdib.h"
static PSTR szExt;
static PSTR szFileName;
static PSTR szTitle;
static DWORD flags;
static WORD fOpt;
/* Forward declarations of helper functions */
static void NEAR DlgCheckOkEnable(HWND hwnd, int idEdit, unsigned message);
static char *NEAR FillListBox (HWND,char*);
static BOOL NEAR FSearchSpec (char*);
static void NEAR AddExt (char*,char*);
extern PASCAL chdir(LPSTR); /* in dlgopena.asm */
#define DLGOPEN_UNUSED 0
/* Mask to eliminate bogus style and bitcount combinations ...
* RLE formats, if chosen should be matched with the bitcounts:
* RLE4 scheme should be used only for 4 bitcount DIBs.
* RLE8 " " " " " " 8 " "
*
* BITCOUNTMASK is indexed by DLGOPEN_RLE4 >> 4, DLGOPEN_RLE8 >> 4
* and DLGOPEN_RLE8 >> 4
*/
static WORD BITCOUNTMASK[] = { DLGOPEN_UNUSED,
DLGOPEN_1BPP | DLGOPEN_8BPP | DLGOPEN_24BPP,
DLGOPEN_1BPP | DLGOPEN_4BPP | DLGOPEN_24BPP,
DLGOPEN_UNUSED,
0 };
/****************************************************************************
* *
* FUNCTION :DlgOpen(LPSTR szFile) *
* *
* PURPOSE :Display dialog box for opening files. Allow user to interact
* with dialogbox, change directories as necessary, and try to *
* open file if user selects one. Automatically append *
* extension to filename if necessary. *
* This routine correctly parses filenames containing KANJI *
* characters. *
* *
* RETURNS : - Handle to the opened file if legal filename. *
* - 0 if user presses <cancel> *
* - 1 if filename entered is illegal *
* *
****************************************************************************
int FAR PASCAL DlgOpenFile (hwndParent, szTitleIn, flagsIn, szExtIn,
szFileNameIn, pfOpt)
HWND hwndParent;
char *szTitleIn;
DWORD flagsIn;
char *szExtIn;
char *szFileNameIn;
WORD *pfOpt;
{
int fh;
FARPROC lpProc;
char achFile[128];
char achExt[128];
HANDLE hInstance;
WORD w;
if (pfOpt == NULL)
pfOpt = &w;
flags = flagsIn;
fOpt = *pfOpt;
lstrcpy (szFileName = achFile, szFileNameIn);
lstrcpy (szExt = achExt, szExtIn);
szTitle = szTitleIn;
hInstance = GetWindowWord (hwndParent, GWW_HINSTANCE);
/* Show the dialog box */
lpProc = MakeProcInstance ((FARPROC)DlgfnOpen, hInstance);
fh = DialogBox (hInstance, "DlgOpenBox", hwndParent, lpProc);
FreeProcInstance (lpProc);
if (fh != 0){
lstrcpy (szFileNameIn, szFileName);
*pfOpt = fOpt;
}
return fh;
}
/****************************************************************************
* *
* FUNCTION :DlgfnOpen (hwnd, msg, wParam, lParam) *
* *
* PURPOSE :Dialog function for File/Open dialog. *
* *
****************************************************************************
int far PASCAL DlgfnOpen (hwnd, msg, wParam, lParam)
HWND hwnd;
unsigned msg;
WORD wParam;
LONG lParam;
{
int result = -1; /* Assume illegal filename initially */
WORD w;
char c;
WORD f;
OFSTRUCT of;
RECT rc, rcCtl;
HWND hwndT;
BOOL fEnable;
switch (msg) {
case WM_INITDIALOG:
if (szTitle && *szTitle)
SetWindowText (hwnd, szTitle);
/* Set text on <OK> button according to mode (File/Open or File/Save) *
if (flags & OF_SAVE)
SetDlgItemText (hwnd, IDOK, "&Save");
if (flags & OF_OPEN)
SetDlgItemText (hwnd, IDOK, "&Open");
if ((flags & OF_NOOPTIONS) &&
(hwndT = GetDlgItem(hwnd,DLGOPEN_FOLDOUT)))
EnableWindow (hwndT,FALSE);
if (hwndT = GetDlgItem (hwnd, DLGOPEN_SMALL)) {
GetWindowRect (hwnd,&rc);
GetWindowRect (GetDlgItem(hwnd,DLGOPEN_SMALL),&rcCtl);
SetWindowPos (hwnd,
NULL,
0,
0,
rcCtl.left - rc.left,
rc.bottom - rc.top,
SWP_NOZORDER | SWP_NOMOVE);
}
/* fill list box with filenames that match specifications, and
* fill static field with path name.
*/
FillListBox(hwnd,szExt);
/* If in Save mode, set the edit control with default (current)
* file name,and select the corresponding entry in the listbox.
*/
if ((flags & OF_SAVE) && *szFileName) {
SetDlgItemText (hwnd, DLGOPEN_EDIT, szFileName);
SendDlgItemMessage (hwnd,
DLGOPEN_FILE_LISTBOX,
LB_SELECTSTRING,
0,
(LONG)(LPSTR)szFileName);
}
else {
/* Set the edit field with the default extensions... */
if (flags & OF_NOSHOWSPEC)
SetDlgItemText (hwnd, DLGOPEN_EDIT, "");
else
SetDlgItemText (hwnd, DLGOPEN_EDIT, szExt);
}
/* ...and select all text in the edit field */
SendDlgItemMessage (hwnd, DLGOPEN_EDIT, EM_SETSEL, 0, 0x7FFF0000L);
/* check all options that are set */
for ( f = DLGOPEN_1BPP; f; f<<=1)
CheckDlgButton(hwnd, FID(f), fOpt & f);
break;
case WM_COMMAND:
w = wParam;
switch (w) {
case IDOK:
if (IsWindowEnabled (GetDlgItem(hwnd, IDOK))) {
/* Get contents of edit field and add search spec. if it
* does not contain one.
*/
GetDlgItemText (hwnd, DLGOPEN_EDIT, (LPSTR)szFileName, 128);
w = lstrlen(szFileName)-1;
c = szFileName[w];
switch (c) {
case '\\':
case '/':
szFileName[w] = 0;
break;
}
if (chdir ((LPSTR)szFileName))
lstrcpy (szFileName,szExt);
/* Try to open path. If successful, fill listbox with
* contents of new directory. Otherwise, open datafile.
*/
if (FSearchSpec(szFileName)) {
lstrcpy (szExt, FillListBox (hwnd, szFileName));
if (flags & OF_NOSHOWSPEC)
SetDlgItemText (hwnd, DLGOPEN_EDIT, "");
else
SetDlgItemText (hwnd, DLGOPEN_EDIT, szExt);
break;
}
/* Make filename upper case and if it's a legal DOS
* name, try to open the file.
*/
AnsiUpper(szFileName);
AddExt(szFileName,szExt);
result = OpenFile(szFileName, &of, (WORD)flags);
if (result != -1) {
lstrcpy(szFileName,of.szPathName);
}
else if (flags & OF_MUSTEXIST) {
MessageBeep(0);
return 0L;
}
/* Get the state of all checked options */
for (f = DLGOPEN_1BPP; f; f <<= 1){
if (IsDlgButtonChecked (hwnd, FID (f)))
fOpt |= f;
else
fOpt &= ~f;
}
EndDialog (hwnd, result);
}
break;
case DLGOPEN_OPTION + DLGOPEN_RLE4:
case DLGOPEN_OPTION + DLGOPEN_RLE8:
case DLGOPEN_OPTION + DLGOPEN_RGB:
/* Mask out incompatible bitcount options and gray the
* appropriate radiobuttons.
*/
for (f = DLGOPEN_1BPP; f <= DLGOPEN_24BPP; f <<= 1){
fEnable = !(f & BITCOUNTMASK [IDF(w) >> 4 ]);
EnableWindow (GetDlgItem (hwnd, FID(f)), fEnable);
/* If the radiobutton is being grayed, uncheck it and
* and check an "allowed" option so the bitcount group
* is still accessible via the keyboard
*/
if (!fEnable && IsDlgButtonChecked (hwnd, FID (f))){
CheckDlgButton(hwnd, FID(f), FALSE);
CheckDlgButton(hwnd, FID(IDF(w) >> 3), TRUE);
}
}
break;
case IDCANCEL:
/* User pressed cancel. Just take down dialog box. */
EndDialog (hwnd, 0);
break;
/* User single clicked or doubled clicked in listbox -
* Single click means fill edit box with selection.
* Double click means go ahead and open the selection.
*/
case DLGOPEN_FILE_LISTBOX:
case DLGOPEN_DIR_LISTBOX:
switch (HIWORD(lParam)) {
/* Single click case */
case 1:
/* Get selection, which may be either a prefix to a
* new search path or a filename. DlgDirSelect parses
* selection, and appends a backslash if selection
* is a prefix
*/
DlgDirSelect(hwnd,szFileName,wParam);
w = lstrlen(szFileName)-1;
c = szFileName[w];
switch (c) {
case ':':
lstrcat (szFileName,".");
break;
case '\\':
case '/':
szFileName[w] = 0;
break;
}
SetDlgItemText(hwnd, DLGOPEN_EDIT, szFileName);
break;
/* Double click case - first click has already been
* processed as single click
*/
case 2:
PostMessage (hwnd,WM_COMMAND,IDOK,0L);
break;
}
break;
case DLGOPEN_EDIT:
DlgCheckOkEnable(hwnd, DLGOPEN_EDIT, HIWORD(lParam));
break;
case DLGOPEN_FOLDOUT:
GetWindowRect(hwnd,&rc);
GetWindowRect(GetDlgItem(hwnd,DLGOPEN_BIG),&rcCtl);
if ((rcCtl.left <= rc.right) && (rcCtl.top <= rc.bottom))
GetWindowRect (GetDlgItem (hwnd, DLGOPEN_SMALL), &rcCtl);
SetWindowPos (hwnd,
NULL,
0,
0,
rcCtl.left - rc.left,
rc.bottom - rc.top,
SWP_NOZORDER | SWP_NOMOVE);
break;
}
default:
return FALSE;
}
return TRUE;
}
/****************************************************************************
* *
* FUNCTION : static void NEAR DlgCheckOkEnable(hwnd, idEdit, message) *
* *
* PURPOSE : Enables the <OK> button in a dialog box iff the edit item *
* contains text. *
* *
****************************************************************************
static void NEAR DlgCheckOkEnable(hwnd, idEdit, message)
HWND hwnd;
int idEdit;
unsigned message;
{
if (message == EN_CHANGE) {
EnableWindow ( GetDlgItem (hwnd, IDOK),
(BOOL)SendMessage (GetDlgItem (hwnd, idEdit),
WM_GETTEXTLENGTH,
0, 0L));
}
}
/****************************************************************************
* *
* FUNCTION : AddExt (pch, ext) *
* *
* PURPOSE : Add an extension to a filename if none is already specified*
* *
****************************************************************************
static void NEAR AddExt (pch,ext)
char *pch; /* File name */
char *ext; /* Extension to add */
{
char acExt[20];
char *pext = acExt;
while (*ext && *ext != '.')
ext++;
while (*ext && *ext != ';')
*pext++ = *ext++;
*pext = 0;
pext = acExt;
while (*pch == '.') {
pch++;
if ((*pch == '.') && pch[1] == '\\')
pch += 2; /* ..\ */
if (*pch == '\\')
pch++; /* .\ */
}
while (*pch != '\0')
if (*pch++ == '.')
return;
// *pch++ = '.';
do
*pch++ = *pext;
while (*pext++ != '\0');
}
/****************************************************************************
* *
* FUNCTION : FSearchSpec (sz) *
* *
* PURPOSE : Checks to see if NULL-terminated strings contains a "*" or *
* a "?". *
* *
* RETURNS : TRUE - if the above characters are found in the string *
* FALSE - otherwise. *
* *
****************************************************************************
static BOOL NEAR FSearchSpec(sz)
char *sz;
{
for (; *sz ;sz++) {
if (*sz == '*' || *sz == '?')
return TRUE;
}
return FALSE;
}
/****************************************************************************
* *
* FUNCTION : static char * NEAR FillListBox (hDlg,pFile) *
* *
* PURPOSE : Fill list box with filenames that match specifications, and*
* fills the static field with the path name. *
* *
* RETURNS : A pointer to the pathname. *
* *
****************************************************************************
static char * NEAR FillListBox (hDlg,pFile)
HWND hDlg;
char *pFile; /* [path]{list of file wild cards, separated by ';'} */
{
char ach[20];
char *pch;
char *pDir; /* Directory name or path */
pch = pFile;
pDir = ach;
while (*pch && *pch != ';')
pch++;
while ((pch > pFile) && (*pch != '/') && (*pch != '\\'))
pch--;
if (pch > pFile) {
*pch = 0;
lstrcpy (pDir, pFile);
pFile = pch + 1;
}
else {
lstrcpy (pDir,".");
}
DlgDirList (hDlg, pDir, DLGOPEN_DIR_LISTBOX, DLGOPEN_PATH,ATTRDIRLIST);
SendDlgItemMessage (hDlg, DLGOPEN_FILE_LISTBOX, LB_RESETCONTENT, 0, 0L);
SendDlgItemMessage (hDlg, DLGOPEN_FILE_LISTBOX, WM_SETREDRAW, FALSE, 0L);
pDir = pFile; /* save pFile to return */
while (*pFile) {
pch = ach;
while (*pFile==' ')
pFile++;
while (*pFile && *pFile != ';')
*pch++ = *pFile++;
*pch = 0;
if (*pFile)
pFile++;
SendDlgItemMessage (hDlg,
DLGOPEN_FILE_LISTBOX,
LB_DIR,ATTRFILELIST,
(LONG)(LPSTR)ach);
}
SendDlgItemMessage (hDlg, DLGOPEN_FILE_LISTBOX, WM_SETREDRAW, TRUE, 0L);
InvalidateRect (GetDlgItem (hDlg, DLGOPEN_FILE_LISTBOX), NULL, TRUE);
return pDir;
}
DRAWDIB.C
CD-ROM Disc Path: \SAMPCODE\WIN_SDK\SHOWDIB\DRAWDIB.C
/****************************************************************************
* *
* MODULE : DrawDIB.c *
* *
* PURPOSE : Handles most of the SHOWDIB's DIB drawing and clipboard *
* operations. *
* *
* FUNCTIONS : *
* PrintDIB() - Sets the current DIB bits to the *
* printer DC. *
* *
* AppPaint() - Sets the DIB/bitmap bits on the *
* screen or the given device. *
* *
* DrawSelect() - Draws selected clip rectangle on *
* the DC/screen. *
* *
* NormalizeRect() - Swaps reversed rectangle coords. *
* *
* TrackMouse() - Draws rubberbanding rectangle and *
* displays it's dimensions. *
* *
* BandDIB() - Outputs DIB in bands to device. *
* *
* SizeWindow() - Sizes app. window based on client *
* dimensions and style. *
* *
* GetRealClientRect() - Calculates client rectangle dimen- *
* sions if scrollbars are present. *
* *
* SetScrollRanges() - Sets global scroll ranges. *
* *
* CopyHandle() - Makes a copy of memory block. *
* *
* CopyPalette() - Makes a copy of the GDI logical *
* palette. *
* *
* CopyBitmap() - Copies given bitmap to another. *
* *
* CropBitmap() - Crops a bitmap to the given size. *
* *
* RenderFormat() - renders currently displayed DIB *
* in CF_BITMAP or CF_DIB format. *
* *
* RealizeDibFormat() - Realizes the DIB in given format. *
* *
* ErrMsg() - Pops an error message to user. *
* *
* fDialog() - Displays a dialog box. *
* *
* AppAbout() - Shows the About.. dialog box. *
* *
****************************************************************************
#include <windows.h>
#include <io.h>
#include <stdio.h>
#include "showdib.h"
POINT ptSize; /* Stores DIB dimensions */
/****************************************************************************
* *
* FUNCTION : PrintDIB(HWND hWnd, HDC hDC, int x, int y, int dx, int dy)*
* *
* PURPOSE : Set the DIB bits to the printer DC. *
* *
****************************************************************************
void PrintDIB (hWnd, hDC, x, y, dx, dy)
HWND hWnd;
HDC hDC;
int x, y;
int dx, dy;
{
BITMAPINFOHEADER bi;
int dibX, dibY;
int dibDX, dibDY;
if (!bLegitDraw)
return;
DibInfo (hbiCurrent, &bi);
if (IsRectEmpty (&rcClip)){
dibX = 0;
dibY = 0;
dibDX = (int)bi.biWidth;
dibDY = (int)bi.biHeight;
}
else{
dibX = rcClip.left;
dibY = (int)bi.biHeight - 1 - rcClip.bottom;
dibDX = rcClip.right - rcClip.left;
dibDY = rcClip.bottom - rcClip.top;
}
if (hdibCurrent){
/* Stretch the DIB to printer DC */
StretchDibBlt ( hDC,
x,
y,
dx,
dy,
hdibCurrent,
dibX,
dibY,
dibDX,
dibDY,
SRCCOPY);
}
else if (achFileName[0]) {
SetMapMode (hDC, MM_ANISOTROPIC);
SetViewportOrg (hDC, x, y);
SetViewportExt (hDC, dx, dy);
BandDIB (hWnd, hDC, 0, 0);
}
}
/****************************************************************************
* *
* FUNCTION : AppPaint(HWND hWnd, HDC hDC, int x, int y) *
* *
* PURPOSE : Sets the DIB/bitmap bits on the screen or the given device*
* *
****************************************************************************
void AppPaint (hWnd, hDC, x, y)
HWND hWnd;
HDC hDC;
int x, y;
{
HPALETTE hpalT;
BITMAPINFOHEADER bi;
LPBITMAPINFOHEADER lpbi;
SetWindowOrg (hDC, x, y);
SetBkMode (hDC, wTransparent);
if (bLegitDraw) {
hpalT = SelectPalette (hDC, hpalCurrent, FALSE);
RealizePalette (hDC);
if (hbmCurrent && !bDIBToDevice) {
DrawBitmap (hDC, 0, 0, hbmCurrent, SRCCOPY);
}
else if (hdibCurrent) {
DibInfo (hdibCurrent, &bi);
DibBlt (hDC,
0,
0,
(int)bi.biWidth,
(int)bi.biHeight,
hdibCurrent,
0,
0,
SRCCOPY);
}
else if (achFileName[0]) {
BandDIB (hWnd, hDC, 0, 0);
}
SelectPalette(hDC,hpalT,FALSE);
}
DrawSelect(hDC, TRUE);
}
/****************************************************************************
* *
* FUNCTION : DrawSelect(HDC hdc, BOOL fDraw) *
* *
* PURPOSE : Draws the selected clip rectangle with its dimensions on *
* the DC/screen *
* *
****************************************************************************
void DrawSelect( hdc, fDraw)
HDC hdc;
BOOL fDraw;
{
char sz[80];
DWORD dw;
int x,y,len,dx,dy;
HDC hdcBits;
HBITMAP hbm;
if (!IsRectEmpty (&rcClip)) {
/* If a rectangular clip region has been selected, draw it */
PatBlt(hdc, rcClip.left, rcClip.top, rcClip.right-rcClip.le
PatBlt(hdc, rcClip.left, rcClip.bottom, 1, -(rcClip.bottom-rcClip.
PatBlt(hdc, rcClip.right-1, rcClip.top, 1, rcClip.bottom-rcClip.top
PatBlt(hdc, rcClip.right, rcClip.bottom-1, -(rcClip.right-rcClip.le
/* Format the dimensions string ...*/
wsprintf( sz,
"%dx%d",
rcClip.right - rcClip.left,
rcClip.bottom - rcClip.top );
len = lstrlen(sz);
/* ... and center it in the rectangle */
dw = GetTextExtent (hdc, sz, len);
dx = LOWORD (dw);
dy = HIWORD (dw);
x = (rcClip.right + rcClip.left - dx) / 2;
y = (rcClip.bottom + rcClip.top - dy) / 2;
hdcBits = CreateCompatibleDC (hdc);
SetTextColor (hdcBits, 0xFFFFFFL);
SetBkColor (hdcBits, 0x000000L);
/* Output the text to the DC */
if (hbm = CreateBitmap (dx, dy, 1, 1, NULL)){
hbm = SelectObject (hdcBits, hbm);
ExtTextOut (hdcBits, 0, 0, 0, NULL, sz, len, NULL);
BitBlt (hdc, x, y, dx, dy, hdcBits, 0, 0, SRCINVERT);
hbm = SelectObject (hdcBits, hbm);
DeleteObject (hbm);
}
DeleteDC (hdcBits);
}
}
/****************************************************************************
* *
* FUNCTION : NormalizeRect(RECT *prc) *
* *
* PURPOSE : If the rectangle coordinates are reversed, swaps them *
* *
****************************************************************************
void PASCAL NormalizeRect (prc)
RECT *prc;
{
if (prc->right < prc->left)
SWAP(prc->right,prc->left);
if (prc->bottom < prc->top)
SWAP(prc->bottom,prc->top);
}
/****************************************************************************
* *
* FUNCTION : TrackMouse(HWND hwnd, POINT pt) *
* *
* PURPOSE : Draws a rubberbanding rectangle and displays it's *
* dimensions till the mouse button is released *
* *
****************************************************************************
void TrackMouse (hwnd, pt)
HWND hwnd;
POINT pt;
{
POINT ptBase;
HDC hdc;
MSG msg;
POINT ptOrigin;
RECT rcClient;
hdc = GetDC(hwnd);
SetCapture(hwnd);
GetClientRect(hwnd,&rcClient);
/* Get mouse coordinates relative to origin of DIB */
ptOrigin.x = GetScrollPos(hwnd,SB_HORZ);
ptOrigin.y = GetScrollPos(hwnd,SB_VERT);
pt.x += ptOrigin.x;
pt.y += ptOrigin.y;
/* Display the coordinates */
SetWindowOrg(hdc,ptOrigin.x,ptOrigin.y);
DrawSelect(hdc,FALSE);
/* Initialize clip rectangle to the point */
rcClip.left = pt.x;
rcClip.top = pt.y;
rcClip.right = pt.x;
rcClip.bottom = pt.y;
/* Eat mouse messages until a WM_LBUTTONUP is encountered. Meanwhile
* continue to draw a rubberbanding rectangle and display it's dimensions
*/
for (;;){
WaitMessage();
if (PeekMessage(&msg,NULL,WM_MOUSEFIRST,WM_MOUSELAST,PM_REMOVE)){
DrawSelect(hdc,FALSE);
rcClip.left = pt.x;
rcClip.top = pt.y;
rcClip.right = LOWORD(msg.lParam) + ptOrigin.x;
rcClip.bottom = HIWORD(msg.lParam) + ptOrigin.y;
NormalizeRect(&rcClip);
DrawSelect(hdc,TRUE);
if (msg.message == WM_LBUTTONUP)
break;
}
else
continue;
}
ReleaseCapture();
ReleaseDC(hwnd,hdc);
}
/****************************************************************************
* *
* FUNCTION : BandDIB(HWND hWnd, HDC hDC, int x, int y) *
* *
* PURPOSE : Outputs the DIB in bands to a device or the screen, using *
* the maximum possible band size. *
* *
****************************************************************************
void BandDIB (hWnd, hDC, x, y)
HWND hWnd;
HDC hDC;
int x, y;
{
HBITMAP hBitmap, hOld ;
HDC hMemDC ;
LPSTR pBuf;
LPBITMAPINFOHEADER lpbi;
WORD wRead, wActualPosition, wScansLeft ;
DWORD dwMapSize;
DWORD dwScans;
WORD wBitmapHeight;
RECT Rect;
HANDLE hBuf;
BOOL bSuccess = FALSE;
int nBandSize;
HPALETTE hOldMemPal;
HPALETTE hOldPal;
int fh;
OFSTRUCT of;
/* Open the map file and get the information out */
fh = OpenFile (achFileName, (LPOFSTRUCT)&of, OF_READ);
if (fh == -1)
return;
lpbi = (VOID FAR *)GlobalLock(hbiCurrent);
if (!lpbi){
_lclose (fh);
return;
}
/* Compute scan size in bytes */
dwScans = WIDTHBYTES((DWORD)lpbi->biWidth * lpbi->biBitCount);
wBitmapHeight = (WORD)lpbi->biHeight ;
wScansLeft = (WORD)lpbi->biHeight ;
hMemDC = NULL;
for ( nBandSize = wScansLeft;
nBandSize >= MINBAND || nBandSize == wScansLeft;
nBandSize -= BANDINCREMENT) {
/* Attempt to maximize band size by trying to allocate a buffer
* for the given band size. If allocation fails, try again with the
* smaller band size.
*/
hBuf = GlobalAlloc (GMEM_FIXED | GMEM_ZEROINIT, dwScans * nBandSize) ;
if (!hBuf)
continue;
/* Show success and exit loop if we're going to set bits to device. */
if (bDIBToDevice) {
hMemDC = 1;
break;
}
else {
/* Create a device-dependent bitmap to hold the bits */
hBitmap = CreateCompatibleBitmap (hDC,
(WORD)lpbi->biWidth,
nBandSize);
if (!hBitmap) {
/* Try again for the next smaller band size */
GlobalFree (hBuf);
continue;
}
/* Create a memory context for the bitmap */
if (!(hMemDC = CreateCompatibleDC (hDC))) {
GlobalFree (hBuf);
DeleteObject (hBitmap);
continue;
} else
/* Success in creating a DC */
break;
}
}
if (!hMemDC) {
/* We failed allocation , so give error message and quit */
if (GetFocus () == hWnd) {
ErrMsg ("No memory available!");
ValidateRect (hWnd, (LPRECT) (NULL));
} else
MessageBeep(0);
GlobalUnlock(hbiCurrent);
_lclose (fh);
return;
}
pBuf = GlobalLock (hBuf);
/* Calculate number of bytes to be transferred */
dwMapSize = dwScans * nBandSize ;
/* Manipulate palette appropriately */
if (!bDIBToDevice)
hOldMemPal = SelectPalette (hMemDC, hpalCurrent, 0) ;
/* Now get to the start of the map in the file */
_llseek(fh, dwOffset, SEEK_SET);
/* we are now all set to start off */
wActualPosition = wScansLeft ;
Rect.left = 0;
Rect.right = (WORD)lpbi->biWidth;
hOldPal = SelectPalette(hDC, hpalCurrent, 0);
RealizePalette(hDC);
do {
/* Read in nBandSize scans or whatever is left */
if (wScansLeft > nBandSize)
wRead = nBandSize ;
else
wRead = wScansLeft ;
Rect.bottom = wActualPosition;
wActualPosition -= wRead ;
Rect.top = wActualPosition;
dwMapSize = ((DWORD) wRead) * dwScans ;
/* Now read in the map to the global buffer */
if (RectVisible (hDC, &Rect)) {
lread(fh, (LPSTR)pBuf, dwMapSize);
if (bDIBToDevice) {
if (wRead != SetDIBitsToDevice (hDC, x, y,
(WORD)lpbi->biWidth,
wBitmapHeight,
0,
0,
wBitmapHeight - wScansLeft,
wRead,
pBuf,
(LPBITMAPINFO)lpbi,
fPalColors ?
DIB_PAL_COLORS :
DIB_RGB_COLORS)){
ErrMsg ("Could not draw DIB scans to device!");
GlobalUnlock (hBuf);
GlobalFree (hBuf);
GlobalUnlock(hbiCurrent);
_lclose (fh);
return;
}
} else {
lpbi->biHeight = wRead ;
/* Set the DIB bits to a device-dependent format */
if ((WORD)lpbi->biHeight != SetDIBits (hMemDC,
hBitmap,
0,
(WORD)lpbi->biHeight,
pBuf,
(LPBITMAPINFO)lpbi,
fPalColors ?
DIB_PAL_COLORS :
DIB_RGB_COLORS)){
ErrMsg ("Could not draw DIB scans!");
GlobalUnlock (hBuf);
GlobalFree (hBuf);
GlobalUnlock(hbiCurrent);
_lclose (fh);
return;
}
/* Blt own map onto the screen, remembering the point to start */
hOld = SelectObject (hMemDC, hBitmap) ;
if (!BitBlt (hDC, 0, wActualPosition,
(WORD)lpbi->biWidth,
(WORD)lpbi->biHeight,
hMemDC, 0, 0, SRCCOPY)){
ErrMsg ("Could not draw map to screen!");
GlobalUnlock (hBuf);
GlobalFree (hBuf);
GlobalUnlock(hbiCurrent);
_lclose (fh);
return;
}
SelectObject (hMemDC, hOld) ;
/* Restore the value of bitmap height */
lpbi->biHeight = wBitmapHeight ;
}
}
else {
/* This chunk is not visible, seek over the data in the file */
_llseek(fh, dwMapSize, SEEK_CUR);
}
wScansLeft -= wRead ;
} while (wScansLeft > 0 ) ;
/* Delete the objects just created above */
GlobalUnlock (hBuf);
GlobalFree (hBuf);
SelectPalette (hDC, hOldPal, 0);
/* Set success flag */
bSuccess = TRUE;
if (!bDIBToDevice) {
SelectPalette (hMemDC, hOldMemPal, 0);
DeleteDC (hMemDC) ;
DeleteObject (hBitmap) ;
}
GlobalUnlock(hbiCurrent);
/* Close the file */
_lclose (fh);
}
/****************************************************************************
* *
* FUNCTION : SizeWindow(HWND hWnd) *
* *
* PURPOSE : Sizes the app. window based on client dimensions (DIB *
* dimensions) and style. Sets the caption text. *
* *
****************************************************************************
void SizeWindow (hWnd)
HWND hWnd;
{
char *pstr;
char Name[60];
RECT Rectangle;
int dx,dy;
POINT pt;
BITMAPINFOHEADER bi;
/* Get information about current DIB */
DibInfo(hbiCurrent,&bi);
/* Extract the filename from the full pathname */
pstr = achFileName + lstrlen(achFileName) - 1;
while ((*pstr != '\\') && (*pstr != ':') && (pstr >= achFileName))
pstr--;
pstr++;
/* Format filename along with the DIB attributes */
wsprintf (Name,
"%ls (%ls %dx%dx%d%ls)",
(LPSTR)szAppName,
(LPSTR)pstr,
(WORD)bi.biWidth,
(WORD)bi.biHeight,
(WORD)bi.biBitCount,
bi.biCompression == BI_RGB ? (LPSTR)" RGB" :
bi.biCompression == BI_RLE8 ? (LPSTR)" RLE8" : (LPSTR)" RLE4" );
/* Show formatted text in the caption bar */
SetWindowText (hWnd, Name);
/* Store the size in ptSize, so the scroll bars will work. */
ptSize.x = (WORD)bi.biWidth;
ptSize.y = (WORD)bi.biHeight;
if (IsZoomed (hWnd))
SetScrollRanges (hWnd);
else {
Rectangle.left = 0;
Rectangle.top = 0;
Rectangle.right = (WORD)bi.biWidth;
Rectangle.bottom = (WORD)bi.biHeight;
/* Compute the size of the window rectangle based on the given
* client rectangle size and the window style, then size the
* window.
*/
AdjustWindowRect (&Rectangle, dwStyle, TRUE);
SetWindowPos (hWnd, (HWND)NULL, 0, 0,
Rectangle.right - Rectangle.left + 1,
Rectangle.bottom - Rectangle.top + 1,
SWP_NOMOVE | SWP_NOZORDER);
}
InvalidateRect(hWnd,NULL,TRUE);
}
/****************************************************************************
* *
* FUNCTION : GetRealClientRect(HWND hwnd, LPRECT lprc) *
* *
* PURPOSE : Calculates the client rectangle taking scrollbars into *
* consideration. *
* *
****************************************************************************
void GetRealClientRect (hwnd, lprc)
HWND hwnd;
PRECT lprc;
{
DWORD dwStyle;
dwStyle = GetWindowLong (hwnd, GWL_STYLE);
GetClientRect (hwnd,lprc);
if (dwStyle & WS_HSCROLL)
lprc->bottom += GetSystemMetrics (SM_CYHSCROLL);
if (dwStyle & WS_VSCROLL)
lprc->right += GetSystemMetrics (SM_CXVSCROLL);
}
/****************************************************************************
* *
* FUNCTION : SetScrollRanges(hwnd) *
* *
* PURPOSE : *
* *
****************************************************************************
void SetScrollRanges(hwnd)
HWND hwnd;
{
RECT rc;
int iRangeH, iRangeV, i;
static int iSem = 0;
if (!iSem){
iSem++;
GetRealClientRect (hwnd, &rc);
for (i = 0; i < 2; i++){
iRangeV = ptSize.y - rc.bottom;
iRangeH = ptSize.x - rc.right;
if (iRangeH < 0) iRangeH = 0;
if (iRangeV < 0) iRangeV = 0;
if (GetScrollPos ( hwnd,
SB_VERT) > iRangeV ||
GetScrollPos (hwnd, SB_HORZ) > iRangeH)
InvalidateRect (hwnd, NULL, TRUE);
SetScrollRange (hwnd, SB_VERT, 0, iRangeV, TRUE);
SetScrollRange (hwnd, SB_HORZ, 0, iRangeH, TRUE);
GetClientRect (hwnd, &rc);
}
iSem--;
}
}
/*********** THE FOLLOWING FUNCTIONS ARE FOR CLIPBOARD SUPPORT **************
/****************************************************************************
* *
* FUNCTION : CopyHandle (HANDLE h) *
* *
* PURPOSE : Makes a copy of the given global memory block. *
* *
* RETURNS : A handle to the new block. *
* *
****************************************************************************
HANDLE CopyHandle (h)
HANDLE h;
{
BYTE huge *lpCopy;
BYTE huge *lp;
HANDLE hCopy;
DWORD dwLen;
dwLen = GlobalSize (h);
if (hCopy = GlobalAlloc (GHND, dwLen)) {
lpCopy = (BYTE huge *)GlobalLock (hCopy);
lp = (BYTE huge *)GlobalLock (h);
while (dwLen--) *lpCopy++ = *lp++;
GlobalUnlock (hCopy);
GlobalUnlock (h);
}
return hCopy;
}
/****************************************************************************
* *
* FUNCTION : CopyPalette(HPALETTE hpal) *
* *
* PURPOSE : Makes a copy of a GDI logical palette *
* *
* RETURNS : A handle to the new palette. *
* *
****************************************************************************
HPALETTE CopyPalette (hpal)
HPALETTE hpal;
{
PLOGPALETTE ppal;
int nNumEntries;
if (!hpal)
return NULL;
GetObject(hpal,sizeof(int),(LPSTR)&nNumEntries);
if (nNumEntries == 0)
return NULL;
ppal = (PLOGPALETTE)LocalAlloc(LPTR,sizeof(LOGPALETTE) +
nNumEntries * sizeof(PALETTEENTRY));
if (!ppal)
return NULL;
ppal->palVersion = PALVERSION;
ppal->palNumEntries = nNumEntries;
GetPaletteEntries(hpal,0,nNumEntries,ppal->palPalEntry);
hpal = CreatePalette(ppal);
LocalFree((HANDLE)ppal);
return hpal;
}
/****************************************************************************
* *
* FUNCTION : CopyBitmap (HBITMAP hbm) *
* *
* PURPOSE : Copies the given bitmap to another. *
* *
* RETURNS : A handle to the new bitmap. *
* *
****************************************************************************
HBITMAP CopyBitmap (hbm)
HBITMAP hbm;
{
BITMAP bm;
RECT rc;
if (!hbm)
return NULL;
GetObject (hbm, sizeof(BITMAP), (LPSTR)&bm);
rc.left = 0;
rc.top = 0;
rc.right = bm.bmWidth;
rc.bottom = bm.bmHeight;
return CropBitmap (hbm, &rc);
}
/****************************************************************************
* *
* FUNCTION : CropBitmap (hbm,lprect) *
* *
* PURPOSE : Crops a bitmap to a new size specified by the lprect *
* parameter. *
* *
* RETURNS : A handle to the new bitmap. *
* *
****************************************************************************
HBITMAP CropBitmap (hbm, prc)
HBITMAP hbm;
PRECT prc;
{
HDC hMemDCsrc;
HDC hMemDCdst;
HDC hdc;
HBITMAP hNewBm;
BITMAP bm;
int dx,dy;
if (!hbm)
return NULL;
hdc = GetDC (NULL);
hMemDCsrc = CreateCompatibleDC (hdc);
hMemDCdst = CreateCompatibleDC (hdc);
GetObject (hbm, sizeof(BITMAP), (LPSTR)&bm);
dx = prc->right - prc->left;
dy = prc->bottom - prc->top;
hNewBm = CreateBitmap (dx, dy, bm.bmPlanes, bm.bmBitsPixel, NULL);
if (hNewBm){
SelectObject (hMemDCsrc, hbm);
SelectObject (hMemDCdst, hNewBm);
BitBlt (hMemDCdst,
0,
0,
dx,
dy,
hMemDCsrc,
prc->left,
prc->top,
SRCCOPY);
}
ReleaseDC (NULL,hdc);
DeleteDC (hMemDCsrc);
DeleteDC (hMemDCdst);
return hNewBm;
}
/****************************************************************************
* *
* FUNCTION : RenderFormat(int cf) *
* *
* PURPOSE : Renders the currently displayed DIB in CF_DIB or *
* CF_BITMAP format.The bitmap is clipped to the current *
* rcClip. *
* *
* RETURNS : A handle to the DIB *
* *
****************************************************************************
HANDLE RenderFormat (cf)
int cf;
{
HANDLE h = NULL;
HBITMAP hbm;
if (!bLegitDraw)
return NULL;
switch (cf){
case CF_BITMAP:
if (hbmCurrent && !IsRectEmpty (&rcClip))
h = CropBitmap (hbmCurrent, &rcClip);
else{
if (hbmCurrent)
h = CopyBitmap (hbmCurrent);
else if (hdibCurrent)
h = BitmapFromDib (hdibCurrent, hpalCurrent);
else if (achFileName[0] && (hdibCurrent = OpenDIB (achFileName)))
h = BitmapFromDib (hdibCurrent, hpalCurrent);
else
h = NULL;
if (h && !IsRectEmpty (&rcClip)){
hbm = CropBitmap (h,&rcClip);
DeleteObject (h);
h = hbm;
}
}
break;
case CF_DIB:
if (!IsRectEmpty (&rcClip)){
if (hbm = RenderFormat (CF_BITMAP)){
h = DibFromBitmap (hbm, BI_RGB, 0, hpalCurrent);
DeleteObject (hbm);
}
}
else{
if (!hdibCurrent && hbmCurrent)
h = DibFromBitmap (hbmCurrent, BI_RGB, 0, hpalCurrent);
else if (hdibCurrent)
h = CopyHandle (hdibCurrent);
else if (achFileName[0])
h = OpenDIB (achFileName);
else
h = NULL;
}
break;
case CF_PALETTE:
if (hpalCurrent)
h = CopyPalette (hpalCurrent);
break;
}
return h;
}
/****************************************************************************
* *
* FUNCTION : RealizeDibFormat(DWORD biStyle, WORD biBits) *
* *
* PURPOSE : Realize the current DIB in the specifed format *
* This function is used to get a specific format of CF_DIB *
* *
* biStyle DIB format RGB or RLE *
* biBits Bits per pixel 1,4,8,24 *
* *
* RETURNS : A handle to the created DIB. *
* *
****************************************************************************
HANDLE RealizeDibFormat (biStyle, biBits)
DWORD biStyle;
WORD biBits;
{
BITMAPINFOHEADER bi;
if (!bLegitDraw)
return NULL;
DibInfo (hbiCurrent, &bi);
/* Do we have the requested format already? */
if (bi.biCompression == biStyle && bi.biBitCount == biBits){
if (!hdibCurrent)
hdibCurrent = RenderFormat (CF_DIB);
}
else{
if (!hbmCurrent)
hbmCurrent = RenderFormat (CF_BITMAP);
if (hbmCurrent){
if (hdibCurrent)
GlobalFree (hdibCurrent);
hdibCurrent = DibFromBitmap (hbmCurrent, biStyle, biBits, hpalCurrent);
}
}
return hdibCurrent;
}
/****************************************************************************
* *
* FUNCTION : ErrMsg (PSTR sz,...) *
* *
* PURPOSE : Opens a Message box with a error message in it.The user can*
* select the OK button to continue *
* *
* RETURNS : FALSE to indicate an error has occured. *
* *
****************************************************************************
int ErrMsg (PSTR sz,...)
{
char ach[128];
wvsprintf (ach, sz, (LPSTR)(&sz+1)); /* Format the string */
MessageBox (NULL, ach, NULL, MB_OK|MB_ICONEXCLAMATION|MB_APPLMODAL);
return FALSE;
}
/****************************************************************************
* *
* FUNCTION : fDialog(int id,HWND hwnd,FARPROC fpfn) *
* *
* PURPOSE : This function displays a dialog box *
* *
* RETURNS : The exit code. *
* *
****************************************************************************
BOOL fDialog (id, hwnd, fpfn)
int id;
HWND hwnd;
FARPROC fpfn;
{
BOOL f;
HANDLE hInst;
hInst = GetWindowWord (hwnd, GWW_HINSTANCE);
fpfn = MakeProcInstance (fpfn, hInst);
f = DialogBox (hInst, MAKEINTRESOURCE(id), hwnd, fpfn);
FreeProcInstance (fpfn);
return f;
}
/****************************************************************************
* *
* FUNCTION : AppAbout( hDlg, uiMessage, wParam, lParam ) *
* *
* PURPOSE : Dialog function for the About... dialog box *
* *
****************************************************************************
BOOL FAR PASCAL AppAbout( hDlg, uiMessage, wParam, lParam )
HWND hDlg;
unsigned uiMessage;
WORD wParam;
long lParam;
{
switch (uiMessage) {
case WM_COMMAND:
if (wParam == IDOK)
EndDialog (hDlg, TRUE);
break;
case WM_INITDIALOG:
return TRUE;
}
return FALSE;
}
EDITCNTL.C
CD-ROM Disc Path: \SAMPCODE\WIN_SDK\EDITCNTL\EDITCNTL.C
/****************************************************************************
PROGRAM: EditCntl.c
PURPOSE: Creates an edit window
FUNCTIONS:
WinMain() - calls initialization function, processes message loop
InitApplication() - initializes window data and registers window
InitInstance() - saves instance handle and creates main window
MainWndProc() - processes messages
About() - processes messages for "About" dialog box
COMMENTS:
After setting up the application's window, the size of the client
area is determined and a child window is created to use for editing.
****************************************************************************/
#include "windows.h"
#include "editcntl.h"
HANDLE hInst;
HANDLE hAccTable; /* handle to accelerator tab
HWND hEditWnd; /* handle to edit window */
HWND hwnd; /* handle to main windows */
/****************************************************************************
FUNCTION: WinMain(HANDLE, HANDLE, LPSTR, int)
PURPOSE: calls initialization function, processes message loop
****************************************************************************/
int PASCAL WinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow)
HANDLE hInstance;
HANDLE hPrevInstance;
LPSTR lpCmdLine;
int nCmdShow;
{
MSG msg;
if (!hPrevInstance)
if (!InitApplication(hInstance))
return (FALSE);
if (!InitInstance(hInstance, nCmdShow))
return (FALSE);
while (GetMessage(&msg, NULL, NULL, NULL)) {
/* Only translate message if it is not an accelerator message */
if (!TranslateAccelerator(hwnd, hAccTable, &msg)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return (msg.wParam);
}
/****************************************************************************
FUNCTION: InitApplication(HANDLE)
PURPOSE: Initializes window data and registers window class
****************************************************************************/
BOOL InitApplication(hInstance)
HANDLE hInstance;
{
WNDCLASS wc;
wc.style = NULL;
wc.lpfnWndProc = MainWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = "EditCntlMenu";
wc.lpszClassName = "EditCntlWClass";
return (RegisterClass(&wc));
}
/****************************************************************************
FUNCTION: InitInstance(HANDLE, int)
PURPOSE: Saves instance handle and creates main window
****************************************************************************/
BOOL InitInstance(hInstance, nCmdShow)
HANDLE hInstance;
int nCmdShow;
{
RECT Rect;
hInst = hInstance;
hAccTable = LoadAccelerators(hInst, "EditCntlAcc");
hwnd = CreateWindow(
"EditCntlWClass",
"EditCntl Sample Application",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
hInstance,
NULL
);
if (!hwnd)
return (FALSE);
GetClientRect(hwnd, (LPRECT) &Rect);
/* Create a child window */
hEditWnd = CreateWindow("Edit",
NULL,
WS_CHILD | WS_VISIBLE |
ES_MULTILINE |
WS_VSCROLL | WS_HSCROLL |
ES_AUTOHSCROLL | ES_AUTOVSCROLL,
0,
0,
(Rect.right-Rect.left),
(Rect.bottom-Rect.top),
hwnd,
IDC_EDIT, /* Child control i.d. */
hInst,
NULL);
if (!hEditWnd) {
DestroyWindow(hwnd);
return (NULL);
}
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
return (TRUE);
}
/****************************************************************************
FUNCTION: MainWndProc(HWND, unsigned, WORD, LONG)
PURPOSE: Processes messages
MESSAGES:
WM_COMMAND - application menu (About dialog box)
WM_DESTROY - destroy window
****************************************************************************/
long FAR PASCAL MainWndProc(hWnd, message, wParam, lParam)
HWND hWnd;
unsigned message;
WORD wParam;
LONG lParam;
{
FARPROC lpProcAbout;
switch (message) {
case WM_COMMAND:
switch (wParam) {
case IDM_ABOUT:
lpProcAbout = MakeProcInstance(About, hInst);
DialogBox(hInst, "AboutBox", hWnd, lpProcAbout);
FreeProcInstance(lpProcAbout);
break;
/* file menu commands */
case IDM_NEW:
case IDM_OPEN:
case IDM_SAVE:
case IDM_SAVEAS:
case IDM_PRINT:
MessageBox (
GetFocus(),
"Command not implemented",
"EditCntl Sample Application",
MB_ICONASTERISK | MB_OK);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
/* edit menu commands */
case IDM_UNDO:
case IDM_CUT:
case IDM_COPY:
case IDM_PASTE:
case IDM_CLEAR:
MessageBox (
GetFocus(),
"Command not implemented",
"EditCntl Sample Application",
MB_ICONASTERISK | MB_OK);
break;
case IDC_EDIT:
if (HIWORD (lParam) == EN_ERRSPACE) {
MessageBox (
GetFocus ()
, "Out of memory."
, "EditCntl Sample Application"
, MB_ICONHAND | MB_OK
);
}
break;
}
break;
case WM_SETFOCUS:
SetFocus (hEditWnd);
break;
case WM_SIZE:
MoveWindow(hEditWnd, 0, 0, LOWORD(lParam), HIWORD(lParam), TRUE);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return (DefWindowProc(hWnd, message, wParam, lParam));
}
return (NULL);
}
/****************************************************************************
FUNCTION: About(HWND, unsigned, WORD, LONG)
PURPOSE: Processes messages for "About" dialog box
MESSAGES:
WM_INITDIALOG - initialize dialog box
WM_COMMAND - Input received
****************************************************************************/
BOOL FAR PASCAL About(hDlg, message, wParam, lParam)
HWND hDlg;
unsigned message;
WORD wParam;
LONG lParam;
{
switch (message) {
case WM_INITDIALOG:
return (TRUE);
case WM_COMMAND:
if (wParam == IDOK
|| wParam == IDCANCEL) {
EndDialog(hDlg, TRUE);
return (TRUE);
}
break;
}
return (FALSE);
}
EDITFILE.C
CD-ROM Disc Path: \SAMPCODE\WIN_SDK\EDITFILE\EDITFILE.C
/****************************************************************************
PROGRAM: EditFile.c
PURPOSE: Loads, saves, and edits text files
FUNCTIONS:
WinMain() - calls initialization function, processes message loop
InitApplication() - initializes window data and registers window
InitInstance() - saves instance handle and creates main window
MainWndProc() - processes messages
About() - processes messages for "About" dialog box
SaveAsDlg() - save file under different name
OpenDlg() - let user select a file, and open it.
UpdateListBox() - Update the list box of OpenDlg
ChangeDefExt() - Change the default extension
SeparateFile() - Separate filename and pathname
AddExt() - Add default extension
CheckFileName() - Check for wildcards, add extension if needed
SaveFile() - Save current file
QuerySaveFile() - Called when some action might lose current contents
SetNewBuffer() - Set new buffer for edit window
****************************************************************************/
#include "windows.h"
#include "editfile.h"
HANDLE hInst;
HANDLE hAccTable; /* handle to accelerator tab
HWND hEditWnd; /* handle to edit window
/* Additional includes needed for the fstat() function */
#include <sys\types.h>
#include <sys\stat.h>
char FileName[128];
char PathName[128];
char OpenName[128];
char DefPath[128];
char DefSpec[13] = "*.*";
char DefExt[] = ".txt";
char str[255];
HANDLE hEditBuffer; /* handle to editing buffer */
HANDLE hOldBuffer; /* old buffer handle */
HANDLE hHourGlass; /* handle to hourglass cursor
HANDLE hSaveCursor; /* current cursor handle */
int hFile; /* file handle */
int count; /* number of chars read or written
PSTR pBuffer; /* address of read/write buffer
OFSTRUCT OfStruct; /* information from OpenFile()
struct stat FileStatus; /* information from fstat() */
BOOL bChanges = FALSE; /* TRUE if the file is changed
BOOL bSaveEnabled = FALSE; /* TRUE if text in the edit buffer
PSTR pEditBuffer; /* address of the edit buffer
RECT Rect; /* dimension of the client window
HWND hwnd; /* handle to main window
char Untitled[] = /* default window title */
"Edit File - (untitled)";
/****************************************************************************
FUNCTION: WinMain(HANDLE, HANDLE, LPSTR, int)
PURPOSE: calls initialization function, processes message loop
****************************************************************************/
int PASCAL WinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow)
HANDLE hInstance;
HANDLE hPrevInstance;
LPSTR lpCmdLine;
int nCmdShow;
{
MSG msg;
if (!hPrevInstance)
if (!InitApplication(hInstance))
return (FALSE);
if (!InitInstance(hInstance, nCmdShow))
return (FALSE);
while (GetMessage(&msg, NULL, NULL, NULL)) {
/* Only translate message if it is not an accelerator message */
if (!TranslateAccelerator(hwnd, hAccTable, &msg)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return (msg.wParam);
}
/****************************************************************************
FUNCTION: InitApplication(HANDLE)
PURPOSE: Initializes window data and registers window class
****************************************************************************/
BOOL InitApplication(hInstance)
HANDLE hInstance;
{
WNDCLASS wc;
wc.style = NULL;
wc.lpfnWndProc = MainWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = "EditFileMenu";
wc.lpszClassName = "EditFileWClass";
return (RegisterClass(&wc));
}
/****************************************************************************
FUNCTION: InitInstance(HANDLE, int)
PURPOSE: Saves instance handle and creates main window
****************************************************************************/
BOOL InitInstance(hInstance, nCmdShow)
HANDLE hInstance;
int nCmdShow;
{
RECT Rect;
hInst = hInstance;
hAccTable = LoadAccelerators(hInst, "EditFileAcc");
hwnd = CreateWindow(
"EditFileWClass",
"EditFile Sample Application",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
hInstance,
NULL
);
if (!hwnd)
return (FALSE);
GetClientRect(hwnd, (LPRECT) &Rect);
/* Create a child window */
hEditWnd = CreateWindow("Edit",
NULL,
WS_CHILD | WS_VISIBLE |
ES_MULTILINE |
WS_VSCROLL | WS_HSCROLL |
ES_AUTOHSCROLL | ES_AUTOVSCROLL,
0,
0,
(Rect.right-Rect.left),
(Rect.bottom-Rect.top),
hwnd,
IDC_EDIT, /* Child control i.d. */
hInst,
NULL);
if (!hEditWnd) {
DestroyWindow(hwnd);
return (NULL);
}
/* Get an hourglass cursor to use during file transfers */
hHourGlass = LoadCursor(NULL, IDC_WAIT);
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
return (TRUE);
}
/****************************************************************************
FUNCTION: MainWndProc(HWND, unsigned, WORD, LONG)
PURPOSE: Processes messages
MESSAGES:
WM_COMMAND - application menu (About dialog box)
WM_DESTROY - destroy window
WM_SIZE - window size has changed
WM_QUERYENDSESSION - willing to end session?
WM_ENDSESSION - end Windows session
WM_CLOSE - close the window
WM_SIZE - window resized
COMMENTS:
WM_COMMAND processing:
IDM_NEW - query to save current file if there is one and it has
been changed, clear buffer and start new file.
IDM_OPEN - query to save current file if there is one and it
has been changed, open a new file.
IDM_SAVE - save current file, prompt for name if none exists.
IDM_SAVEAS - prompt for new filename to save to, save file.
IDC_EDIT - change "bChanges" flag to indicate if edit buffer has
been modified. Affects actions of IDM_NEW and
IDM_OPEN. Reset when file is saved.
IDM_EXIT - query to save current file if there is one and it
has been changed, then exit.
IDM_ABOUT - display "About" box.
When more then one string needs to be sent to a message box,
sprintf() is used to combine the strings into str[], and then str[]
is passed to the MessageBox() function. A message box string cannot
exceed 255 characters, but may contain \n to generate separate
lines.
After the size of the file is determined, only enough memory to store
the file is allocated for the Edit buffer. The edit control will
automatically expand this memory as needed. Once the file has been
read into the edit buffer, unlock the memory. Use whatever was
obtained from the read() function, even if an error occured. This
allows partial salvage of a file with a bad sector.
****************************************************************************/
long FAR PASCAL MainWndProc(hWnd, message, wParam, lParam)
HWND hWnd;
unsigned message;
WORD wParam;
LONG lParam;
{
FARPROC lpProcAbout, lpOpenDlg, lpSaveAsDlg;
int Success; /* return value from SaveAsDlg()
int IOStatus; /* result of file i/o */
switch (message) {
case WM_COMMAND:
switch (wParam) {
case IDM_ABOUT:
lpProcAbout = MakeProcInstance(About, hInst);
DialogBox(hInst, "AboutBox", hWnd, lpProcAbout);
FreeProcInstance(lpProcAbout);
break;
case IDM_NEW:
/* If current file has been modified, query user about
* saving it.
*/
if (!QuerySaveFile(hWnd))
return (NULL);
/* bChanges is set to FALSE to indicate there have been
* no changes since the last file save.
*/
bChanges = FALSE;
FileName[0] = 0;
/* Update the edit buffer */
SetNewBuffer(hWnd, NULL, Untitled);
break;
case IDM_OPEN:
if (!QuerySaveFile(hWnd))
return (NULL);
lpOpenDlg = MakeProcInstance((FARPROC) OpenDlg, hInst);
/* Open the file and get its handle */
hFile = DialogBox(hInst, "Open", hWnd, lpOpenDlg);
FreeProcInstance(lpOpenDlg);
if (!hFile)
return (NULL);
/* Allocate edit buffer to the size of the file + 1 */
hEditBuffer =
LocalAlloc(LMEM_MOVEABLE | LMEM_ZEROINIT,
(WORD)(FileStatus.st_size+1));
if (!hEditBuffer) {
MessageBox(hWnd, "Not enough memory.",
NULL, MB_OK | MB_ICONHAND);
return (NULL);
}
hSaveCursor = SetCursor(hHourGlass);
pEditBuffer = LocalLock(hEditBuffer);
IOStatus = read(hFile, pEditBuffer, FileStatus.st_size);
close(hFile);
/* # bytes read must equal file size */
if (IOStatus != FileStatus.st_size) {
sprintf(str, "Error reading %s.", FileName);
SetCursor(hSaveCursor); /* Remove the hourglass
MessageBox(hWnd, str, NULL, MB_OK | MB_ICONEXCLAMATIO
}
LocalUnlock(hEditBuffer);
/* Set up a new buffer and window title */
sprintf(str, "EditFile - %s", FileName);
SetNewBuffer(hWnd, hEditBuffer, str);
SetCursor(hSaveCursor); /* restore the cursor
break;
case IDM_SAVE:
/* If there is no filename, use the saveas command to get
* one. Otherwise, save the file using the current
* filename.
*/
if (!FileName[0])
goto saveas;
if (bChanges)
SaveFile(hWnd);
break;
case IDM_SAVEAS:
saveas:
lpSaveAsDlg = MakeProcInstance(SaveAsDlg, hInst);
/* Call the SaveAsDlg() function to get the new filename
Success = DialogBox(hInst, "SaveAs", hWnd, lpSaveAsDlg);
FreeProcInstance(lpSaveAsDlg);
/* If successful, update the window title, save the file
if (Success == IDOK) {
sprintf(str, "EditFile - %s", FileName);
SetWindowText(hWnd, str);
SaveFile(hWnd);
}
break; /* User canceled
case IDM_PRINT:
MessageBox (
GetFocus(),
"Command not implemented",
"EditFile Sample Application",
MB_ICONASTERISK | MB_OK);
break;
/* edit menu commands */
case IDM_UNDO:
case IDM_CUT:
case IDM_COPY:
case IDM_PASTE:
case IDM_CLEAR:
MessageBox (
GetFocus(),
"Command not implemented",
"EditFile Sample Application",
MB_ICONASTERISK | MB_OK);
break;
case IDM_EXIT:
QuerySaveFile(hWnd);
DestroyWindow(hWnd);
break;
case IDC_EDIT:
if (HIWORD (lParam) == EN_ERRSPACE) {
MessageBox (
GetFocus ()
, "Out of memory."
, "EditFile Sample Application"
, MB_ICONHAND | MB_OK
);
}
break;
}
break;
case WM_SETFOCUS:
SetFocus (hEditWnd);
break;
case WM_SIZE:
MoveWindow(hEditWnd, 0, 0, LOWORD(lParam), HIWORD(lParam), TRUE);
break;
case WM_QUERYENDSESSION: /* message: to end the session?
return (QuerySaveFile(hWnd));
case WM_CLOSE: /* message: close the window
if (QuerySaveFile(hWnd))
DestroyWindow(hWnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return (DefWindowProc(hWnd, message, wParam, lParam));
}
return (NULL);
}
/****************************************************************************
FUNCTION: SaveAsDlg(HWND, unsigned, WORD, LONG)
PURPOSE: Allows user to change name to save file to
COMMENTS:
This will initialize the window class if it is the first time this
application is run. It then creates the window, and processes the
message loop until a PostQuitMessage is received. It exits the
application by returning the value passed by the PostQuitMessage.
****************************************************************************/
int FAR PASCAL SaveAsDlg(hDlg, message, wParam, lParam)
HWND hDlg;
unsigned message;
WORD wParam;
LONG lParam;
{
char TempName[128];
switch (message) {
case WM_INITDIALOG:
/* If no filename is entered, don't allow the user to save to it
if (!FileName[0])
bSaveEnabled = FALSE;
else {
bSaveEnabled = TRUE;
/* Process the path to fit within the IDC_PATH field */
DlgDirList(hDlg, DefPath, NULL, IDC_PATH, 0x4010);
/* Send the current filename to the edit control */
SetDlgItemText(hDlg, IDC_EDIT, FileName);
/* Accept all characters in the edit control */
SendDlgItemMessage(hDlg, IDC_EDIT, EM_SETSEL, 0,
MAKELONG(0, 0x7fff));
}
/* Enable or disable the save control depending on whether the
* filename exists.
*/
EnableWindow(GetDlgItem(hDlg, IDOK), bSaveEnabled);
/* Set the focus to the edit control within the dialog box */
SetFocus(GetDlgItem(hDlg, IDC_EDIT));
return (FALSE); /* FALSE since Focus was changed
case WM_COMMAND:
switch (wParam) {
case IDC_EDIT:
/* If there was previously no filename in the edit
* control, then the save control must be enabled as soon
* a character is entered.
*/
if (HIWORD(lParam) == EN_CHANGE && !bSaveEnabled)
EnableWindow(GetDlgItem(hDlg, IDOK), bSaveEnabled = TRUE)
return (TRUE);
case IDOK:
/* Get the filename from the edit control */
GetDlgItemText(hDlg, IDC_EDIT, TempName, 128);
/* If there are no wildcards, then separate the name into
* path and name. If a path was specified, replace the
* default path with the new path.
*/
if (CheckFileName(hDlg, FileName, TempName)) {
SeparateFile(hDlg, (LPSTR) str, (LPSTR) DefSpec,
(LPSTR) FileName);
if (str[0])
strcpy(DefPath, str);
/* Tell the caller a filename was selected */
EndDialog(hDlg, IDOK);
}
return (TRUE);
case IDCANCEL:
/* Tell the caller the user canceled the SaveAs function
EndDialog(hDlg, IDCANCEL);
return (TRUE);
}
break;
}
return (FALSE);
}
/****************************************************************************
FUNCTION: OpenDlg(HWND, unsigned, WORD, LONG)
PURPOSE: Let user select a file, and open it.
****************************************************************************/
HANDLE FAR PASCAL OpenDlg(hDlg, message, wParam, lParam)
HWND hDlg;
unsigned message;
WORD wParam;
LONG lParam;
{
WORD index;
PSTR pTptr;
HANDLE hFile;
switch (message) {
case WM_COMMAND:
switch (wParam) {
case IDC_LISTBOX:
switch (HIWORD(lParam)) {
case LBN_SELCHANGE:
/* If item is a directory name, append "*.*" */
if (DlgDirSelect(hDlg, str, IDC_LISTBOX))
strcat(str, DefSpec);
SetDlgItemText(hDlg, IDC_EDIT, str);
SendDlgItemMessage(hDlg,
IDC_EDIT,
EM_SETSEL,
NULL,
MAKELONG(0, 0x7fff));
break;
case LBN_DBLCLK:
goto openfile;
}
return (TRUE);
case IDOK:
openfile:
GetDlgItemText(hDlg, IDC_EDIT, OpenName, 128);
if (strchr(OpenName, '*') || strchr(OpenName, '?')) {
SeparateFile(hDlg, (LPSTR) str, (LPSTR) DefSpec,
(LPSTR) OpenName);
if (str[0])
strcpy(DefPath, str);
ChangeDefExt(DefExt, DefSpec);
UpdateListBox(hDlg);
return (TRUE);
}
if (!OpenName[0]) {
MessageBox(hDlg, "No filename specified.",
NULL, MB_OK | MB_ICONHAND);
return (TRUE);
}
AddExt(OpenName, DefExt);
/* Open the file */
if ((hFile = OpenFile(OpenName, (LPOFSTRUCT) &OfStruct,
OF_READ)) == -1) {
sprintf(str, "Error %d opening %s.",
OfStruct.nErrCode, OpenName);
MessageBox(hDlg, str, NULL,
MB_OK | MB_ICONHAND);
}
else {
/* Make sure there's enough room for the file */
fstat(hFile, &FileStatus);
if (FileStatus.st_size > MAXFILESIZE) {
sprintf(str,
"Not enough memory to load %s.\n%s exceeds %ld bytes.",
OpenName, OpenName, MAXFILESIZE);
MessageBox(hDlg, str, NULL,
MB_OK | MB_ICONHAND);
return (TRUE);
}
/* File is opened and there is enough room so return
* the handle to the caller.
*/
strcpy(FileName, OpenName);
EndDialog(hDlg, hFile);
return (TRUE);
}
return (TRUE);
case IDCANCEL:
EndDialog(hDlg, NULL);
return (TRUE);
}
break;
case WM_INITDIALOG: /* message: initialize
UpdateListBox(hDlg);
SetDlgItemText(hDlg, IDC_EDIT, DefSpec);
SendDlgItemMessage(hDlg, /* dialog handle */
IDC_EDIT, /* where to send message
EM_SETSEL, /* select characters
NULL, /* additional information
MAKELONG(0, 0x7fff)); /* entire contents */
SetFocus(GetDlgItem(hDlg, IDC_EDIT));
return (FALSE); /* Indicates the focus is set to a control */
}
return FALSE;
}
/****************************************************************************
FUNCTION: UpdateListBox(HWND);
PURPOSE: Update the list box of OpenDlg
****************************************************************************/
void UpdateListBox(hDlg)
HWND hDlg;
{
strcpy(str, DefPath);
strcat(str, DefSpec);
DlgDirList(hDlg, str, IDC_LISTBOX, IDC_PATH, 0x4010);
/* To ensure that the listing is made for a subdir. of
* current drive dir...
*/
if (!strchr (DefPath, ':'))
DlgDirList(hDlg, DefSpec, IDC_LISTBOX, IDC_PATH, 0x4010);
/* Remove the '..' character from path if it exists, since this
* will make DlgDirList move us up an additional level in the tree
* when UpdateListBox() is called again.
*/
if (strstr (DefPath, ".."))
DefPath[0] = '\0';
SetDlgItemText(hDlg, IDC_EDIT, DefSpec);
}
/****************************************************************************
FUNCTION: ChangeDefExt(PSTR, PSTR);
PURPOSE: Change the default extension
****************************************************************************/
void ChangeDefExt(Ext, Name)
PSTR Ext, Name;
{
PSTR pTptr;
pTptr = Name;
while (*pTptr && *pTptr != '.')
pTptr++;
if (*pTptr)
if (!strchr(pTptr, '*') && !strchr(pTptr, '?'))
strcpy(Ext, pTptr);
}
/****************************************************************************
FUNCTION: SeparateFile(HWND, LPSTR, LPSTR, LPSTR)
PURPOSE: Separate filename and pathname
****************************************************************************/
void SeparateFile(hDlg, lpDestPath, lpDestFileName, lpSrcFileName)
HWND hDlg;
LPSTR lpDestPath, lpDestFileName, lpSrcFileName;
{
LPSTR lpTmp;
char cTmp;
lpTmp = lpSrcFileName + (long) lstrlen(lpSrcFileName);
while (*lpTmp != ':' && *lpTmp != '\\' && lpTmp > lpSrcFileName)
lpTmp = AnsiPrev(lpSrcFileName, lpTmp);
if (*lpTmp != ':' && *lpTmp != '\\') {
lstrcpy(lpDestFileName, lpSrcFileName);
lpDestPath[0] = 0;
return;
}
lstrcpy(lpDestFileName, lpTmp + 1);
cTmp = *(lpTmp + 1);
lstrcpy(lpDestPath, lpSrcFileName);
*(lpTmp + 1) = cTmp;
lpDestPath[(lpTmp - lpSrcFileName) + 1] = 0;
}
/****************************************************************************
FUNCTION: AddExt(PSTR, PSTR);
PURPOSE: Add default extension
/***************************************************************************/
void AddExt(Name, Ext)
PSTR Name, Ext;
{
PSTR pTptr;
pTptr = Name;
while (*pTptr && *pTptr != '.')
pTptr++;
if (*pTptr != '.')
strcat(Name, Ext);
}
/****************************************************************************
FUNCTION: CheckFileName(HWND, PSTR, PSTR)
PURPOSE: Check for wildcards, add extension if needed
COMMENTS:
Make sure you have a filename and that it does not contain any
wildcards. If needed, add the default extension. This function is
called whenever your application wants to save a file.
****************************************************************************/
BOOL CheckFileName(hWnd, pDest, pSrc)
HWND hWnd;
PSTR pDest, pSrc;
{
PSTR pTmp;
if (!pSrc[0])
return (FALSE); /* Indicates no filename was specified
pTmp = pSrc;
while (*pTmp) { /* Searches the string for wildcards
switch (*pTmp++) {
case '*':
case '?':
MessageBox(hWnd, "Wildcards not allowed.",
NULL, MB_OK | MB_ICONEXCLAMATION);
return (FALSE);
}
}
AddExt(pSrc, DefExt); /* Adds the default extension if needed
if (OpenFile(pSrc, (LPOFSTRUCT) &OfStruct, OF_EXIST) >= 0) {
sprintf(str, "Replace existing %s?", pSrc);
if (MessageBox(hWnd, str, "EditFile",
MB_OKCANCEL | MB_ICONHAND) == IDCANCEL)
return (FALSE);
}
strcpy(pDest, pSrc);
return (TRUE);
}
/****************************************************************************
FUNCTION: SaveFile(HWND)
PURPOSE: Save current file
COMMENTS:
This saves the current contents of the Edit buffer, and changes
bChanges to indicate that the buffer has not been changed since the
last save.
Before the edit buffer is sent, you must get its handle and lock it
to get its address. Once the file is written, you must unlock the
buffer. This allows Windows to move the buffer when not in immediate
use.
****************************************************************************/
BOOL SaveFile(hWnd)
HWND hWnd;
{
BOOL bSuccess;
int IOStatus; /* result of a file write
if ((hFile = OpenFile(FileName, &OfStruct,
OF_PROMPT | OF_CANCEL | OF_CREATE)) < 0) {
/* If the file can't be saved */
sprintf(str, "Cannot write to %s.", FileName);
MessageBox(hWnd, str, NULL, MB_OK | MB_ICONEXCLAMATION);
return (FALSE);
}
hEditBuffer = SendMessage(hEditWnd, EM_GETHANDLE, 0, 0L);
pEditBuffer = LocalLock(hEditBuffer);
/* Set the cursor to an hourglass during the file transfer */
hSaveCursor = SetCursor(hHourGlass);
IOStatus = write(hFile, pEditBuffer, strlen(pEditBuffer));
close(hFile);
SetCursor(hSaveCursor);
if (IOStatus != strlen(pEditBuffer)) {
sprintf(str, "Error writing to %s.", FileName);
MessageBox(hWnd, str,
NULL, MB_OK | MB_ICONHAND);
bSuccess = FALSE;
}
else {
bSuccess = TRUE; /* Indicates the file was saved
bChanges = FALSE; /* Indicates changes have been saved
}
LocalUnlock(hEditBuffer);
return (bSuccess);
}
/****************************************************************************
FUNCTION: QuerySaveFile(HWND);
PURPOSE: Called when some action might lose current contents
COMMENTS:
This function is called whenever we are about to take an action that
would lose the current contents of the edit buffer.
****************************************************************************/
BOOL QuerySaveFile(hWnd)
HWND hWnd;
{
int Response;
FARPROC lpSaveAsDlg;
if (bChanges) {
sprintf(str, "Save current changes: %s", FileName);
Response = MessageBox(hWnd, str,
"EditFile", MB_YESNOCANCEL | MB_ICONEXCLAMATION);
if (Response == IDYES) {
check_name:
/* Make sure there is a filename to save to */
if (!FileName[0]) {
lpSaveAsDlg = MakeProcInstance(SaveAsDlg, hInst);
Response = DialogBox(hInst, "SaveAs",
hWnd, lpSaveAsDlg);
FreeProcInstance(lpSaveAsDlg);
if (Response == IDOK)
goto check_name;
else
return (FALSE);
}
SaveFile(hWnd);
}
else if (Response == IDCANCEL)
return (FALSE);
}
else
return (TRUE);
}
/****************************************************************************
FUNCTION: SetNewBuffer(HWND, HANDLE, PSTR)
PURPOSE: Set new buffer for edit window
COMMENTS:
Point the edit window to the new buffer, update the window title, and
redraw the edit window. If hNewBuffer is NULL, then create an empty
1K buffer, and return its handle.
****************************************************************************/
void SetNewBuffer(hWnd, hNewBuffer, Title)
HWND hWnd;
HANDLE hNewBuffer;
PSTR Title;
{
HANDLE hOldBuffer;
hOldBuffer = SendMessage(hEditWnd, EM_GETHANDLE, 0, 0L);
LocalFree(hOldBuffer);
if (!hNewBuffer) /* Allocates a buffer if none exists
hNewBuffer = LocalAlloc(LMEM_MOVEABLE | LMEM_ZEROINIT, 1);
/* Updates the buffer and displays new buffer */
SendMessage(hEditWnd, EM_SETHANDLE, hNewBuffer, 0L);
SetWindowText(hWnd, Title);
SetFocus(hEditWnd);
bChanges = FALSE;
}
/****************************************************************************
FUNCTION: About(HWND, unsigned, WORD, LONG)
PURPOSE: Processes messages for "About" dialog box
MESSAGES:
WM_INITDIALOG - initialize dialog box
WM_COMMAND - Input received
****************************************************************************/
BOOL FAR PASCAL About(hDlg, message, wParam, lParam)
HWND hDlg;
unsigned message;
WORD wParam;
LONG lParam;
{
switch (message) {
case WM_INITDIALOG:
return (TRUE);
case WM_COMMAND:
if (wParam == IDOK
|| wParam == IDCANCEL) {
EndDialog(hDlg, TRUE);
return (TRUE);
}
break;
}
return (FALSE);
}
EDITMENU.C
CD-ROM Disc Path: \SAMPCODE\WIN_SDK\EDITMENU\EDITMENU.C
/****************************************************************************
PROGRAM: EditMenu.c
PURPOSE: EditMenu template for Windows applications
FUNCTIONS:
WinMain() - calls initialization function, processes message loop
InitApplication() - initializes window data and registers window
InitInstance() - saves instance handle and creates main window
MainWndProc() - processes messages
About() - processes messages for "About" dialog box
****************************************************************************/
#include "windows.h"
#include "editmenu.h"
HANDLE hInst;
HANDLE hAccTable; /* handle to accelerator tab
HWND hwnd; /* handle to main window */
/****************************************************************************
FUNCTION: WinMain(HANDLE, HANDLE, LPSTR, int)
PURPOSE: calls initialization function, processes message loop
****************************************************************************/
int PASCAL WinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow)
HANDLE hInstance;
HANDLE hPrevInstance;
LPSTR lpCmdLine;
int nCmdShow;
{
MSG msg;
if (!hPrevInstance)
if (!InitApplication(hInstance))
return (FALSE);
if (!InitInstance(hInstance, nCmdShow))
return (FALSE);
while (GetMessage(&msg, NULL, NULL, NULL)) {
/* Only translate message if it is not an accelerator message */
if (!TranslateAccelerator(hwnd, hAccTable, &msg)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return (msg.wParam);
}
/****************************************************************************
FUNCTION: InitApplication(HANDLE)
PURPOSE: Initializes window data and registers window class
****************************************************************************/
BOOL InitApplication(hInstance)
HANDLE hInstance;
{
WNDCLASS wc;
wc.style = NULL;
wc.lpfnWndProc = MainWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = "EditMenuMenu";
wc.lpszClassName = "EditMenuWClass";
return (RegisterClass(&wc));
}
/****************************************************************************
FUNCTION: InitInstance(HANDLE, int)
PURPOSE: Saves instance handle and creates main window
****************************************************************************/
BOOL InitInstance(hInstance, nCmdShow)
HANDLE hInstance;
int nCmdShow;
{
hInst = hInstance;
hAccTable = LoadAccelerators(hInst, "EditMenuAcc");
hwnd = CreateWindow(
"EditMenuWClass",
"EditMenu Sample Application",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
hInstance,
NULL
);
if (!hwnd)
return (FALSE);
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
return (TRUE);
}
/****************************************************************************
FUNCTION: MainWndProc(HWND, unsigned, WORD, LONG)
PURPOSE: Processes messages
MESSAGES:
WM_COMMAND - application menu (About dialog box)
WM_DESTROY - destroy window
****************************************************************************/
long FAR PASCAL MainWndProc(hWnd, message, wParam, lParam)
HWND hWnd;
unsigned message;
WORD wParam;
LONG lParam;
{
FARPROC lpProcAbout;
switch (message) {
case WM_COMMAND:
switch (wParam) {
case IDM_ABOUT:
lpProcAbout = MakeProcInstance(About, hInst);
DialogBox(hInst, "AboutBox", hWnd, lpProcAbout);
FreeProcInstance(lpProcAbout);
break;
/* file menu commands */
case IDM_NEW:
case IDM_OPEN:
case IDM_SAVE:
case IDM_SAVEAS:
case IDM_PRINT:
MessageBox (
GetFocus(),
"Command not implemented",
"EditMenu Sample Application",
MB_ICONASTERISK | MB_OK);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
/* edit menu commands */
case IDM_UNDO:
case IDM_CUT:
case IDM_COPY:
case IDM_PASTE:
case IDM_CLEAR:
MessageBox (
GetFocus(),
"Command not implemented",
"EditMenu Sample Application",
MB_ICONASTERISK | MB_OK);
break;
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return (DefWindowProc(hWnd, message, wParam, lParam));
}
return (NULL);
}
/****************************************************************************
FUNCTION: About(HWND, unsigned, WORD, LONG)
PURPOSE: Processes messages for "About" dialog box
MESSAGES:
WM_INITDIALOG - initialize dialog box
WM_COMMAND - Input received
****************************************************************************/
BOOL FAR PASCAL About(hDlg, message, wParam, lParam)
HWND hDlg;
unsigned message;
WORD wParam;
LONG lParam;
{
switch (message) {
case WM_INITDIALOG:
return (TRUE);
case WM_COMMAND:
if (wParam == IDOK
|| wParam == IDCANCEL) {
EndDialog(hDlg, TRUE);
return (TRUE);
}
break;
}
return (FALSE);
}
FILEOPEN.C
CD-ROM Disc Path: \SAMPCODE\WIN_SDK\FILEOPEN\FILEOPEN.C
/****************************************************************************
PROGRAM: FileOpen.c
PURPOSE: Loads, saves, and edits text files
FUNCTIONS:
WinMain() - calls initialization function, processes message loop
InitApplication() - initializes window data and registers window
InitInstance() - saves instance handle and creates main window
MainWndProc() - processes messages
About() - processes messages for "About" dialog box
OpenDlg() - let user select a file, and open it.
UpdateListBox() - Update the list box of OpenDlg
ChangeDefExt() - Change the default extension
SeparateFile() - Separate filename and pathname
AddExt() - Add default extension
****************************************************************************/
#include "windows.h"
#include "fileopen.h"
HANDLE hInst;
HANDLE hAccTable; /* handle to accelerator tab
HWND hEditWnd; /* handle to edit window
HWND hwnd; /* handle to main window */
char FileName[128];
char PathName[128];
char OpenName[128];
char DefPath[128];
char DefSpec[13] = "*.*";
char DefExt[] = ".txt";
char str[255];
/****************************************************************************
FUNCTION: WinMain(HANDLE, HANDLE, LPSTR, int)
PURPOSE: calls initialization function, processes message loop
****************************************************************************/
int PASCAL WinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow)
HANDLE hInstance;
HANDLE hPrevInstance;
LPSTR lpCmdLine;
int nCmdShow;
{
MSG msg;
if (!hPrevInstance)
if (!InitApplication(hInstance))
return (FALSE);
if (!InitInstance(hInstance, nCmdShow))
return (FALSE);
while (GetMessage(&msg, NULL, NULL, NULL)) {
/* Only translate message if it is not an accelerator message */
if (!TranslateAccelerator(hwnd, hAccTable, &msg)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return (msg.wParam);
}
/****************************************************************************
FUNCTION: InitApplication(HANDLE)
PURPOSE: Initializes window data and registers window class
****************************************************************************/
BOOL InitApplication(hInstance)
HANDLE hInstance;
{
WNDCLASS wc;
wc.style = NULL;
wc.lpfnWndProc = MainWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = "FileOpenMenu";
wc.lpszClassName = "FileOpenWClass";
return (RegisterClass(&wc));
}
/****************************************************************************
FUNCTION: InitInstance(HANDLE, int)
PURPOSE: Saves instance handle and creates main window
****************************************************************************/
BOOL InitInstance(hInstance, nCmdShow)
HANDLE hInstance;
int nCmdShow;
{
RECT Rect;
hInst = hInstance;
hAccTable = LoadAccelerators(hInst, "FileOpenAcc");
hwnd = CreateWindow(
"FileOpenWClass",
"FileOpen Sample Application",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
hInstance,
NULL
);
if (!hwnd)
return (FALSE);
GetClientRect(hwnd, (LPRECT) &Rect);
/* Create a child window */
hEditWnd = CreateWindow("Edit",
NULL,
WS_CHILD | WS_VISIBLE |
ES_MULTILINE |
WS_VSCROLL | WS_HSCROLL |
ES_AUTOHSCROLL | ES_AUTOVSCROLL,
0,
0,
(Rect.right-Rect.left),
(Rect.bottom-Rect.top),
hwnd,
IDC_EDIT, /* Child control i.d. */
hInst,
NULL);
if (!hEditWnd) {
DestroyWindow(hwnd);
return (NULL);
}
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
return (TRUE);
}
/****************************************************************************
FUNCTION: MainWndProc(HWND, unsigned, WORD, LONG)
PURPOSE: Processes messages
MESSAGES:
WM_COMMAND - application menu (About dialog box)
WM_DESTROY - destroy window
COMMENTS:
WM_COMMAND processing:
IDM_OPEN - query to save current file if there is one and it
has been changed, open a new file.
IDM_ABOUT - display "About" box.
****************************************************************************/
long FAR PASCAL MainWndProc(hWnd, message, wParam, lParam)
HWND hWnd;
unsigned message;
WORD wParam;
LONG lParam;
{
FARPROC lpProcAbout, lpOpenDlg, lpSaveAsDlg;
int Success; /* return value from SaveAsDlg()
int IOStatus; /* result of file i/o */
int Return;
switch (message) {
case WM_COMMAND:
switch (wParam) {
case IDM_ABOUT:
lpProcAbout = MakeProcInstance(About, hInst);
DialogBox(hInst, "AboutBox", hWnd, lpProcAbout);
FreeProcInstance(lpProcAbout);
break;
case IDM_OPEN:
/* Call OpenDlg() to get the filename */
lpOpenDlg = MakeProcInstance((FARPROC) OpenDlg, hInst);
Return = DialogBox(hInst, "Open", hWnd, lpOpenDlg);
FreeProcInstance(lpOpenDlg);
/* Let user know that "open" functionality is not yet
implemented */
if (Return)
MessageBox (
GetFocus(),
"Command not implemented",
"FileOpen Sample Application",
MB_ICONASTERISK | MB_OK);
break;
case IDM_NEW:
case IDM_SAVE:
case IDM_SAVEAS:
case IDM_PRINT:
MessageBox (
GetFocus(),
"Command not implemented",
"FileOpen Sample Application",
MB_ICONASTERISK | MB_OK);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
/* edit menu commands */
case IDM_UNDO:
case IDM_CUT:
case IDM_COPY:
case IDM_PASTE:
case IDM_CLEAR:
MessageBox (
GetFocus(),
"Command not implemented",
"FileOpen Sample Application",
MB_ICONASTERISK | MB_OK);
break;
case IDC_EDIT:
if (HIWORD (lParam) == EN_ERRSPACE) {
MessageBox (
GetFocus ()
, "Out of memory."
, "FileOpen Sample Application"
, MB_ICONHAND | MB_OK
);
}
break;
}
break;
case WM_SETFOCUS:
SetFocus (hEditWnd);
break;
case WM_SIZE:
MoveWindow(hEditWnd, 0, 0, LOWORD(lParam), HIWORD(lParam), TRUE);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return (DefWindowProc(hWnd, message, wParam, lParam));
}
return (NULL);
}
/****************************************************************************
FUNCTION: OpenDlg(HWND, unsigned, WORD, LONG)
PURPOSE: Let user select a file, and return. Open code not provided.
****************************************************************************/
HANDLE FAR PASCAL OpenDlg(hDlg, message, wParam, lParam)
HWND hDlg;
unsigned message;
WORD wParam;
LONG lParam;
{
WORD index;
PSTR pTptr;
HANDLE hFile=1; /* Temp value for return */
switch (message) {
case WM_COMMAND:
switch (wParam) {
case IDC_LISTBOX:
switch (HIWORD(lParam)) {
case LBN_SELCHANGE:
/* If item is a directory name, append "*.*" */
if (DlgDirSelect(hDlg, str, IDC_LISTBOX))
strcat(str, DefSpec);
SetDlgItemText(hDlg, IDC_EDIT, str);
SendDlgItemMessage(hDlg,
IDC_EDIT,
EM_SETSEL,
NULL,
MAKELONG(0, 0x7fff));
break;
case LBN_DBLCLK:
goto openfile;
}
return (TRUE);
case IDOK:
openfile:
GetDlgItemText(hDlg, IDC_EDIT, OpenName, 128);
if (strchr(OpenName, '*') || strchr(OpenName, '?')) {
SeparateFile(hDlg, (LPSTR) str, (LPSTR) DefSpec,
(LPSTR) OpenName);
if (str[0])
strcpy(DefPath, str);
ChangeDefExt(DefExt, DefSpec);
UpdateListBox(hDlg);
return (TRUE);
}
if (!OpenName[0]) {
MessageBox(hDlg, "No filename specified.",
NULL, MB_OK | MB_ICONHAND);
return (TRUE);
}
AddExt(OpenName, DefExt);
/* The routine to open the file would go here, and the */
/* file handle would be returned instead of NULL.
EndDialog(hDlg, hFile);
return (TRUE);
case IDCANCEL:
EndDialog(hDlg, NULL);
return (FALSE);
}
break;
case WM_INITDIALOG: /* message: initialize
UpdateListBox(hDlg);
SetDlgItemText(hDlg, IDC_EDIT, DefSpec);
SendDlgItemMessage(hDlg, /* dialog handle */
IDC_EDIT, /* where to send message
EM_SETSEL, /* select characters
NULL, /* additional information
MAKELONG(0, 0x7fff)); /* entire contents */
SetFocus(GetDlgItem(hDlg, IDC_EDIT));
return (FALSE); /* Indicates the focus is set to a control */
}
return FALSE;
}
/****************************************************************************
FUNCTION: UpdateListBox(HWND);
PURPOSE: Update the list box of OpenDlg
****************************************************************************/
void UpdateListBox(hDlg)
HWND hDlg;
{
strcpy(str, DefPath);
strcat(str, DefSpec);
DlgDirList(hDlg, str, IDC_LISTBOX, IDC_PATH, 0x4010);
/* To ensure that the listing is made for a subdir. of
* current drive dir...
*/
if (!strchr (DefPath, ':'))
DlgDirList(hDlg, DefSpec, IDC_LISTBOX, IDC_PATH, 0x4010);
/* Remove the '..' character from path if it exists, since this
* will make DlgDirList move us up an additional level in the tree
* when UpdateListBox() is called again.
*/
if (strstr (DefPath, ".."))
DefPath[0] = '\0';
SetDlgItemText(hDlg, IDC_EDIT, DefSpec);
}
/****************************************************************************
FUNCTION: ChangeDefExt(PSTR, PSTR);
PURPOSE: Change the default extension
****************************************************************************/
void ChangeDefExt(Ext, Name)
PSTR Ext, Name;
{
PSTR pTptr;
pTptr = Name;
while (*pTptr && *pTptr != '.')
pTptr++;
if (*pTptr)
if (!strchr(pTptr, '*') && !strchr(pTptr, '?'))
strcpy(Ext, pTptr);
}
/****************************************************************************
FUNCTION: SeparateFile(HWND, LPSTR, LPSTR, LPSTR)
PURPOSE: Separate filename and pathname
****************************************************************************/
void SeparateFile(hDlg, lpDestPath, lpDestFileName, lpSrcFileName)
HWND hDlg;
LPSTR lpDestPath, lpDestFileName, lpSrcFileName;
{
LPSTR lpTmp;
char cTmp;
lpTmp = lpSrcFileName + (long) lstrlen(lpSrcFileName);
while (*lpTmp != ':' && *lpTmp != '\\' && lpTmp > lpSrcFileName)
lpTmp = AnsiPrev(lpSrcFileName, lpTmp);
if (*lpTmp != ':' && *lpTmp != '\\') {
lstrcpy(lpDestFileName, lpSrcFileName);
lpDestPath[0] = 0;
return;
}
lstrcpy(lpDestFileName, lpTmp + 1);
cTmp = *(lpTmp + 1);
lstrcpy(lpDestPath, lpSrcFileName);
*(lpTmp + 1) = cTmp;
lpDestPath[(lpTmp - lpSrcFileName) + 1] = 0;
}
/****************************************************************************
FUNCTION: AddExt(PSTR, PSTR);
PURPOSE: Add default extension
/***************************************************************************/
void AddExt(Name, Ext)
PSTR Name, Ext;
{
PSTR pTptr;
pTptr = Name;
while (*pTptr && *pTptr != '.')
pTptr++;
if (*pTptr != '.')
strcat(Name, Ext);
}
/****************************************************************************
FUNCTION: About(HWND, unsigned, WORD, LONG)
PURPOSE: Processes messages for "About" dialog box
MESSAGES:
WM_INITDIALOG - initialize dialog box
WM_COMMAND - Input received
****************************************************************************/
BOOL FAR PASCAL About(hDlg, message, wParam, lParam)
HWND hDlg;
unsigned message;
WORD wParam;
LONG lParam;
{
switch (message) {
case WM_INITDIALOG:
return (TRUE);
case WM_COMMAND:
if (wParam == IDOK
|| wParam == IDCANCEL) {
EndDialog(hDlg, TRUE);
return (TRUE);
}
break;
}
return (FALSE);
}
GENERIC.C
CD-ROM Disc Path: \SAMPCODE\WIN_SDK\GENERIC\GENERIC.C
/****************************************************************************
PROGRAM: Generic.c
PURPOSE: Generic template for Windows applications
FUNCTIONS:
WinMain() - calls initialization function, processes message loop
InitApplication() - initializes window data and registers window
InitInstance() - saves instance handle and creates main window
MainWndProc() - processes messages
About() - processes messages for "About" dialog box
COMMENTS:
Windows can have several copies of your application running at the
same time. The variable hInst keeps track of which instance this
application is so that processing will be to the correct window.
****************************************************************************/
"windows.h" /* required for all Windows applications */
"generic.h" /* specific to this program */
HANDLE hInst; /* current instance */
/****************************************************************************
FUNCTION: WinMain(HANDLE, HANDLE, LPSTR, int)
PURPOSE: calls initialization function, processes message loop
COMMENTS:
Windows recognizes this function by name as the initial entry point
for the program. This function calls the application initialization
routine, if no other instance of the program is running, and always
calls the instance initialization routine. It then executes a messag
retrieval and dispatch loop that is the top-level control structure
for the remainder of execution. The loop is terminated when a WM_QUI
message is received, at which time this function exits the applicatio
instance by returning the value passed by PostQuitMessage().
If this function must abort before entering the message loop, it
returns the conventional value NULL.
****************************************************************************/
int PASCAL WinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow)
HANDLE hInstance; /* current instance */
HANDLE hPrevInstance; /* previous instance */
LPSTR lpCmdLine; /* command line */
int nCmdShow; /* show-window type (open/icon) */
{
MSG msg; /* message */
if (!hPrevInstance) /* Other instances of app running? */
if (!InitApplication(hInstance)) /* Initialize shared things */
return (FALSE); /* Exits if unable to initialize */
/* Perform initializations that apply to a specific instance */
if (!InitInstance(hInstance, nCmdShow))
return (FALSE);
/* Acquire and dispatch messages until a WM_QUIT message is received. */
while (GetMessage(&msg, /* message structure */
NULL, /* handle of window receiving the message */
NULL, /* lowest message to examine */
NULL)) /* highest message to examine */
{
TranslateMessage(&msg); /* Translates virtual key codes */
DispatchMessage(&msg); /* Dispatches message to window */
}
return (msg.wParam); /* Returns the value from PostQuitMessage */
}
/****************************************************************************
FUNCTION: InitApplication(HANDLE)
PURPOSE: Initializes window data and registers window class
COMMENTS:
This function is called at initialization time only if no other
instances of the application are running. This function performs
initialization tasks that can be done once for any number of running
instances.
In this case, we initialize a window class by filling out a data
structure of type WNDCLASS and calling the Windows RegisterClass()
function. Since all instances of this application use the same windo
class, we only need to do this when the first instance is initialized
****************************************************************************/
BOOL InitApplication(hInstance)
HANDLE hInstance; /* current instance */
{
WNDCLASS wc;
/* Fill in window class structure with parameters that describe the
/* main window.
wc.style = NULL; /* Class style(s).
wc.lpfnWndProc = MainWndProc; /* Function to retrieve messages for
/* windows of this class.
wc.cbClsExtra = 0; /* No per-class extra data.
wc.cbWndExtra = 0; /* No per-window extra data.
wc.hInstance = hInstance; /* Application that owns the class.
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = "GenericMenu"; /* Name of menu resource in .RC file.
wc.lpszClassName = "GenericWClass"; /* Name used in call to CreateWindow.
/* Register the window class and return success/failure code. */
return (RegisterClass(&wc));
}
/****************************************************************************
FUNCTION: InitInstance(HANDLE, int)
PURPOSE: Saves instance handle and creates main window
COMMENTS:
This function is called at initialization time for every instance of
this application. This function performs initialization tasks that
cannot be shared by multiple instances.
In this case, we save the instance handle in a static variable and
create and display the main program window.
****************************************************************************/
BOOL InitInstance(hInstance, nCmdShow)
HANDLE hInstance; /* Current instance identifier.
int nCmdShow; /* Param for first ShowWindow() call.
{
HWND hWnd; /* Main window handle.
/* Save the instance handle in static variable, which will be used in */
/* many subsequence calls from this application to Windows. */
hInst = hInstance;
/* Create a main window for this application instance. */
hWnd = CreateWindow(
"GenericWClass", /* See RegisterClass() call.
"Generic Sample Application", /* Text for window title bar.
WS_OVERLAPPEDWINDOW, /* Window style.
CW_USEDEFAULT, /* Default horizontal position.
CW_USEDEFAULT, /* Default vertical position.
CW_USEDEFAULT, /* Default width.
CW_USEDEFAULT, /* Default height.
NULL, /* Overlapped windows have no parent.
NULL, /* Use the window class menu.
hInstance, /* This instance owns this window.
NULL /* Pointer not needed.
);
/* If window could not be created, return "failure" */
if (!hWnd)
return (FALSE);
/* Make the window visible; update its client area; and return "success"
ShowWindow(hWnd, nCmdShow); /* Show the window */
UpdateWindow(hWnd); /* Sends WM_PAINT message */
return (TRUE); /* Returns the value from PostQuitMessage */
}
/****************************************************************************
FUNCTION: MainWndProc(HWND, unsigned, WORD, LONG)
PURPOSE: Processes messages
MESSAGES:
WM_COMMAND - application menu (About dialog box)
WM_DESTROY - destroy window
COMMENTS:
To process the IDM_ABOUT message, call MakeProcInstance() to get the
current instance address of the About() function. Then call Dialog
box which will create the box according to the information in your
generic.rc file and turn control over to the About() function. When
it returns, free the intance address.
****************************************************************************/
long FAR PASCAL MainWndProc(hWnd, message, wParam, lParam)
HWND hWnd; /* window handle */
unsigned message; /* type of message */
WORD wParam; /* additional information */
LONG lParam; /* additional information */
{
FARPROC lpProcAbout; /* pointer to the "About" function */
switch (message) {
case WM_COMMAND: /* message: command from application menu */
if (wParam == IDM_ABOUT) {
lpProcAbout = MakeProcInstance(About, hInst);
DialogBox(hInst, /* current instance */
"AboutBox", /* resource to use */
hWnd, /* parent handle */
lpProcAbout); /* About() instance address */
FreeProcInstance(lpProcAbout);
break;
}
else /* Lets Windows process it */
return (DefWindowProc(hWnd, message, wParam, lParam));
case WM_DESTROY: /* message: window being destroyed */
PostQuitMessage(0);
break;
default: /* Passes it on if unproccessed */
return (DefWindowProc(hWnd, message, wParam, lParam));
}
return (NULL);
}
/****************************************************************************
FUNCTION: About(HWND, unsigned, WORD, LONG)
PURPOSE: Processes messages for "About" dialog box
MESSAGES:
WM_INITDIALOG - initialize dialog box
WM_COMMAND - Input received
COMMENTS:
No initialization is needed for this particular dialog box, but TRUE
must be returned to Windows.
Wait for user to click on "Ok" button, then close the dialog box.
****************************************************************************/
BOOL FAR PASCAL About(hDlg, message, wParam, lParam)
HWND hDlg; /* window handle of the dialog box
unsigned message; /* type of message
WORD wParam; /* message-specific information
LONG lParam;
{
switch (message) {
case WM_INITDIALOG: /* message: initialize dialog box */
return (TRUE);
case WM_COMMAND: /* message: received a command */
if (wParam == IDOK /* "OK" box selected? */
|| wParam == IDCANCEL) { /* System menu close command? *
EndDialog(hDlg, TRUE); /* Exits the dialog box */
return (TRUE);
}
break;
}
return (FALSE); /* Didn't process a message */
}
HELPEX.C
CD-ROM Disc Path: \SAMPCODE\WIN_SDK\HELPEX\HELPEX.C
/****************************************************************************
PROGRAM: HelpEx.c
PURPOSE: Illustrates calls to WinHelp and context-sensitive help.
HelpEx loads library MenuHook, which detects F1 keystrokes in
the HelpEx application menus.
FUNCTIONS:
WinMain() - Calls initialization function, processes message loop.
InitApplication() - Initializes window data and registers window class.
InitInstance() - Saves instance handle and creates main window.
MainWndProc() - Processes window messages.
About() - Processes messages for "About" dialog box.
MakeHelpPathName() - Derives path name of help file.
****************************************************************************/
#include <windows.h>
#include "helpex.h"
#include "helpids.h"
HWND hWnd; /* Handle to main window */
HANDLE hInst; /* Handle to instance data*/
BOOL bHelp = FALSE; /* Help mode flag; TRUE = "ON"*/
HCURSOR hHelpCursor; /* Cursor displayed when in help mode*/
char szHelpFileName[EXE_NAME_MAX_SIZE+1]; /* Help file name*/
HANDLE hAccTable; /* handle to accelerator t
void MakeHelpPathName(char*); /* Function deriving help file path */
/****************************************************************************
FUNCTION: WinMain(HANDLE, HANDLE, LPSTR, int)
PURPOSE: Calls initialization function, processes message loop.
****************************************************************************/
int PASCAL WinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow)
HANDLE hInstance;
HANDLE hPrevInstance;
LPSTR lpCmdLine;
int nCmdShow;
{
MSG msg;
if (!hPrevInstance)
if (!InitApplication(hInstance))
return (FALSE);
if (!InitInstance(hInstance, nCmdShow))
return (FALSE);
while (GetMessage(&msg, NULL, NULL, NULL)) {
/* Only translate message if it is not an accelerator message */
if (!TranslateAccelerator(hWnd, hAccTable, &msg)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return (msg.wParam);
}
/****************************************************************************
FUNCTION: InitApplication(HANDLE)
PURPOSE: Initializes window data and registers window class.
RETURNS: Status of RegisterClass() call.
****************************************************************************/
BOOL InitApplication(hInstance)
HANDLE hInstance;
{
WNDCLASS wc;
wc.style = NULL;
wc.lpfnWndProc = MainWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = GetStockObject(WHITE_BRUSH);
wc.lpszMenuName ="HelpexMenu";
wc.lpszClassName = "HelpexWClass";
return (RegisterClass(&wc));
}
/****************************************************************************
FUNCTION: InitInstance(HANDLE, int)
PURPOSE: Saves instance handle in global variable and creates main
window.
RETURNS: Status of CreateWindow() call.
****************************************************************************/
BOOL InitInstance(hInstance, nCmdShow)
HANDLE hInstance;
int nCmdShow;
{
hInst = hInstance;
hAccTable = LoadAccelerators(hInst, "HelpexAcc");
hWnd = CreateWindow(
"HelpexWClass",
"Help Example ",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
hInstance,
NULL
);
if (!hWnd)
return (FALSE);
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
EnableMenuItem(GetSubMenu(GetMenu(hWnd), 1), IDM_CLEAR, MF_ENABLED);
MakeHelpPathName(szHelpFileName);
hHelpCursor = LoadCursor(hInst,"HelpCursor");
return (TRUE);
}
/****************************************************************************
FUNCTION: MainWndProc(HWND, unsigned, WORD, LONG)
PURPOSE: Processes window messages.
MESSAGES:
WM_COMMAND- Application menu item
WM_DESTROY- Destroy window
****************************************************************************/
long FAR PASCAL MainWndProc(hWnd, message, wParam, lParam)
HWND hWnd;
unsigned message;
WORD wParam;
LONG lParam;
{
FARPROC lpProcAbout;
DWORD dwHelpContextId;
RECT rect;
POINT pt;
DWORD dword;
WORD wFormat;
HCURSOR hArrow;
switch (message) {
case WM_COMMAND:
/* Was F1 just pressed in a menu, or are we in help mode */
/* (Shift-F1)? */
if (bHelp) {
dwHelpContextId =
(wParam == IDM_NEW) ? (DWORD) HELPID_FILE_NEW :
(wParam == IDM_OPEN) ? (DWORD) HELPID_FILE_OPEN :
(wParam == IDM_SAVE) ? (DWORD) HELPID_FILE_SAVE :
(wParam == IDM_SAVEAS) ? (DWORD) HELPID_FILE_SAVE_AS :
(wParam == IDM_PRINT) ? (DWORD) HELPID_FILE_PRINT :
(wParam == IDM_EXIT) ? (DWORD) HELPID_FILE_EXIT :
(wParam == IDM_UNDO) ? (DWORD) HELPID_EDIT_UNDO :
(wParam == IDM_CUT) ? (DWORD) HELPID_EDIT_CUT :
(wParam == IDM_CLEAR) ? (DWORD) HELPID_EDIT_CLEAR :
(wParam == IDM_COPY) ? (DWORD) HELPID_EDIT_COPY :
(wParam == IDM_PASTE) ? (DWORD) HELPID_EDIT_PASTE :
(DWORD) 0L;
if (!dwHelpContextId)
{
MessageBox( hWnd, "Help not available for Help Menu item",
"Help Example", MB_OK );
return (DefWindowProc(hWnd, message, wParam, lParam));
}
bHelp = FALSE;
WinHelp(hWnd,szHelpFileName,HELP_CONTEXT,dwHelpContextId);
break;
}
switch (wParam) {
case IDM_NEW:
case IDM_OPEN:
case IDM_SAVE:
case IDM_SAVEAS:
case IDM_PRINT:
case IDM_UNDO:
case IDM_CUT:
case IDM_CLEAR:
case IDM_COPY:
case IDM_PASTE:
MessageBox(hWnd,
"Command not implemented",
"Help Example",
MB_OK);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
case IDM_HELP_INDEX:
WinHelp(hWnd,szHelpFileName,HELP_INDEX,0L);
break;
case IDM_HELP_KEYBOARD:
WinHelp(hWnd,szHelpFileName,HELP_KEY,(DWORD)(LPSTR)"keys");
break;
case IDM_HELP_HELP:
WinHelp(hWnd,"WINHELP.HLP",HELP_INDEX,0L);
break;
case IDM_ABOUT:
lpProcAbout = MakeProcInstance(About, hInst);
DialogBox(hInst,
"AboutBox",
hWnd,
lpProcAbout);
FreeProcInstance(lpProcAbout);
break;
default:
return (DefWindowProc(hWnd, message, wParam, lParam));
}
break;
case WM_LBUTTONDOWN:
if (bHelp)
{
bHelp = FALSE;
WinHelp( hWnd, szHelpFileName, HELP_CONTEXT,
(DWORD) HELPID_EDIT_WINDOW );
break;
}
return (DefWindowProc(hWnd, message, wParam, lParam));
case WM_NCLBUTTONDOWN:
/* If we are in help mode (Shift-F1) then display context- */
/* sensitive help for non-client area. */
if (bHelp) {
dwHelpContextId =
(wParam == HTCAPTION) ? (DWORD) HELPID_TITLE_BAR :
(wParam == HTREDUCE) ? (DWORD) HELPID_MINIMIZE_ICON :
(wParam == HTZOOM) ? (DWORD) HELPID_MAXIMIZE_ICON :
(wParam == HTSYSMENU) ? (DWORD) HELPID_SYSTEM_MENU :
(wParam == HTBOTTOM) ? (DWORD) HELPID_SIZING_BORDER :
(wParam == HTBOTTOMLEFT) ? (DWORD) HELPID_SIZING_BORDER :
(wParam == HTBOTTOMRIGHT) ? (DWORD) HELPID_SIZING_BORDER :
(wParam == HTTOP) ? (DWORD) HELPID_SIZING_BORDER :
(wParam == HTLEFT) ? (DWORD) HELPID_SIZING_BORDER :
(wParam == HTRIGHT) ? (DWORD) HELPID_SIZING_BORDER :
(wParam == HTTOPLEFT) ? (DWORD) HELPID_SIZING_BORDER :
(wParam == HTTOPRIGHT) ? (DWORD) HELPID_SIZING_BORDER :
(DWORD) 0L;
if (!((BOOL)dwHelpContextId))
return (DefWindowProc(hWnd, message, wParam, lParam));
bHelp = FALSE;
WinHelp(hWnd,szHelpFileName,HELP_CONTEXT,dwHelpContextId);
break;
}
return (DefWindowProc(hWnd, message, wParam, lParam));
case WM_KEYDOWN:
if (wParam == VK_F1) {
/* If Shift-F1, turn help mode on and set help cursor */
if (GetKeyState(VK_SHIFT)<0) {
bHelp = TRUE;
SetCursor(hHelpCursor);
return (DefWindowProc(hWnd, message, wParam, lParam));
}
/* If F1 without shift, then call up help main index topic */
else {
WinHelp(hWnd,szHelpFileName,HELP_INDEX,0L);
}
}
else if (wParam == VK_ESCAPE && bHelp) {
/* Escape during help mode: turn help mode off */
bHelp = FALSE;
SetCursor((HCURSOR)GetClassWord(hWnd,GCW_HCURSOR));
}
break;
case WM_SETCURSOR:
/* In help mode it is necessary to reset the cursor in response */
/* to every WM_SETCURSOR message.Otherwise, by default, Windows */
/* will reset the cursor to that of the window class. */
if (bHelp) {
SetCursor(hHelpCursor);
break;
}
return (DefWindowProc(hWnd, message, wParam, lParam));
break;
case WM_INITMENU:
if (bHelp) {
SetCursor(hHelpCursor);
}
return (TRUE);
case WM_ENTERIDLE:
if ((wParam == MSGF_MENU) && (GetKeyState(VK_F1) & 0x8000)) {
bHelp = TRUE;
PostMessage(hWnd, WM_KEYDOWN, VK_RETURN, 0L);
}
break;
case WM_DESTROY:
WinHelp(hWnd,szHelpFileName,HELP_QUIT,0L);
PostQuitMessage(0);
break;
default:
return (DefWindowProc(hWnd, message, wParam, lParam));
}
return (NULL);
}
/****************************************************************************
FUNCTION: About(HWND, unsigned, WORD, LONG)
PURPOSE: Processes messages for "About" dialog box
MESSAGES:
WM_INITDIALOG - Initialize dialog box
WM_COMMAND- Input received
****************************************************************************/
BOOL FAR PASCAL About(hDlg, message, wParam, lParam)
HWND hDlg;
unsigned message;
WORD wParam;
LONG lParam;
{
switch (message) {
case WM_INITDIALOG:
return (TRUE);
case WM_COMMAND:
if (wParam == IDOK) {
EndDialog(hDlg, TRUE);
return (TRUE);
}
break;
}
return (FALSE);
}
/****************************************************************************
FUNCTION: MakeHelpPathName
PURPOSE: HelpEx assumes that the .HLP help file is in the same
directory as the HelpEx executable.This function derives
the full path name of the help file from the path of the
executable.
****************************************************************************/
void MakeHelpPathName(szFileName)
char * szFileName;
{
char * pcFileName;
int nFileNameLen;
nFileNameLen = GetModuleFileName(hInst,szFileName,EXE_NAME_MAX_SIZE);
pcFileName = szFileName + nFileNameLen;
while (pcFileName > szFileName) {
if (*pcFileName == '\\' || *pcFileName == ':') {
*(++pcFileName) = '\0';
break;
}
nFileNameLen--;
pcFileName--;
}
if ((nFileNameLen+13) < EXE_NAME_MAX_SIZE) {
lstrcat(szFileName, "helpex.hlp");
}
else {
lstrcat(szFileName, "?");
}
return;
}
ICON.C
CD-ROM Disc Path: \SAMPCODE\WIN_SDK\ICON\ICON.C
/****************************************************************************
PROGRAM: Icon.c
PURPOSE: Demonstrates using an icon for the About box and minimize box
FUNCTIONS:
WinMain() - calls initialization function, processes message loop
InitApplication() - initializes window data and registers window
InitInstance() - saves instance handle and creates main window
MainWndProc() - processes messages
About() - processes messages for "About" dialog box
****************************************************************************/
#include "windows.h"
#include "icon.h"
HANDLE hInst;
/****************************************************************************
FUNCTION: WinMain(HANDLE, HANDLE, LPSTR, int)
PURPOSE: calls initialization function, processes message loop
****************************************************************************/
int PASCAL WinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow)
HANDLE hInstance;
HANDLE hPrevInstance;
LPSTR lpCmdLine;
int nCmdShow;
{
MSG msg;
if (!hPrevInstance)
if (!InitApplication(hInstance))
return (FALSE);
if (!InitInstance(hInstance, nCmdShow))
return (FALSE);
while (GetMessage(&msg, NULL, NULL, NULL)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (msg.wParam);
}
/****************************************************************************
FUNCTION: InitApplication(HANDLE)
PURPOSE: Initializes window data and registers window class
****************************************************************************/
BOOL InitApplication(hInstance)
HANDLE hInstance;
{
WNDCLASS wc;
wc.style = NULL;
wc.lpfnWndProc = MainWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(hInstance, "MyIcon"); /* loads icon */
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = "IconMenu";
wc.lpszClassName = "IconWClass";
return (RegisterClass(&wc));
}
/****************************************************************************
FUNCTION: InitInstance(HANDLE, int)
PURPOSE: Saves instance handle and creates main window
****************************************************************************/
BOOL InitInstance(hInstance, nCmdShow)
HANDLE hInstance;
int nCmdShow;
{
HWND hWnd;
hInst = hInstance;
hWnd = CreateWindow(
"IconWClass",
"Icon Sample Application",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
hInstance,
NULL
);
if (!hWnd)
return (FALSE);
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return (TRUE);
}
/****************************************************************************
FUNCTION: MainWndProc(HWND, unsigned, WORD, LONG)
PURPOSE: Processes messages
MESSAGES:
WM_COMMAND - application menu (About dialog box)
WM_DESTROY - destroy window
****************************************************************************/
long FAR PASCAL MainWndProc(hWnd, message, wParam, lParam)
HWND hWnd;
unsigned message;
WORD wParam;
LONG lParam;
{
FARPROC lpProcAbout;
switch (message) {
case WM_COMMAND:
if (wParam == IDM_ABOUT) {
lpProcAbout = MakeProcInstance(About, hInst);
DialogBox(hInst,
"AboutBox",
hWnd,
lpProcAbout);
FreeProcInstance(lpProcAbout);
break;
}
else
return (DefWindowProc(hWnd, message, wParam, lParam));
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return (DefWindowProc(hWnd, message, wParam, lParam));
}
return (NULL);
}
/****************************************************************************
FUNCTION: About(HWND, unsigned, WORD, LONG)
PURPOSE: Processes messages for "About" dialog box
MESSAGES:
WM_INITDIALOG - initialize dialog box
WM_COMMAND - Input received
****************************************************************************/
BOOL FAR PASCAL About(hDlg, message, wParam, lParam)
HWND hDlg;
unsigned message;
WORD wParam;
LONG lParam;
{
switch (message) {
case WM_INITDIALOG:
return (TRUE);
case WM_COMMAND:
if (wParam == IDOK
|| wParam == IDCANCEL) {
EndDialog(hDlg, TRUE);
return (TRUE);
}
break;
}
return (FALSE);
}
INPUT.C
CD-ROM Disc Path: \SAMPCODE\WIN_SDK\INPUT\INPUT.C
/****************************************************************************
PROGRAM: Input.c
PURPOSE: Input template for Windows applications
FUNCTIONS:
WinMain() - calls initialization function, processes message loop
InitApplication() - initializes window data and registers window
InitInstance() - saves instance handle and creates main window
MainWndProc() - processes messages
About() - processes messages for "About" dialog box
****************************************************************************/
#include "windows.h"
#include "input.h"
HANDLE hInst;
char MouseText[48]; /* mouse state
char ButtonText[48]; /* mouse-button state
char KeyboardText[48]; /* keyboard state
char CharacterText[48]; /* latest character
char ScrollText[48]; /* scroll status
char TimerText[48]; /* timer state
RECT rectMouse;
RECT rectButton;
RECT rectKeyboard;
RECT rectCharacter;
RECT rectScroll;
RECT rectTimer;
int idTimer; /* timer ID
int nTimerCount = 0; /* current timer count
/****************************************************************************
FUNCTION: WinMain(HANDLE, HANDLE, LPSTR, int)
PURPOSE: calls initialization function, processes message loop
****************************************************************************/
int PASCAL WinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow)
HANDLE hInstance;
HANDLE hPrevInstance;
LPSTR lpCmdLine;
int nCmdShow;
{
MSG msg;
if (!hPrevInstance)
if (!InitApplication(hInstance))
return (FALSE);
if (!InitInstance(hInstance, nCmdShow))
return (FALSE);
while (GetMessage(&msg, NULL, NULL, NULL)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (msg.wParam);
}
/****************************************************************************
FUNCTION: InitApplication(HANDLE)
PURPOSE: Initializes window data and registers window class
****************************************************************************/
BOOL InitApplication(hInstance)
HANDLE hInstance;
{
WNDCLASS wc;
wc.style = CS_DBLCLKS; /* double-click messages */
wc.lpfnWndProc = MainWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = "InputMenu";
wc.lpszClassName = "InputWClass";
return (RegisterClass(&wc));
}
/****************************************************************************
FUNCTION: InitInstance(HANDLE, int)
PURPOSE: Saves instance handle and creates main window
****************************************************************************/
BOOL InitInstance(hInstance, nCmdShow)
HANDLE hInstance;
int nCmdShow;
{
HWND hWnd;
HDC hDC;
TEXTMETRIC textmetric;
RECT rect;
int nLineHeight;
hInst = hInstance;
hWnd = CreateWindow(
"InputWClass",
"Input Sample Application",
WS_OVERLAPPEDWINDOW | WS_HSCROLL | WS_VSCROLL, /* horz & vert scroll
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
hInstance,
NULL
);
if (!hWnd)
return (FALSE);
hDC = GetDC(hWnd);
GetTextMetrics(hDC, &textmetric);
ReleaseDC(hWnd, hDC);
nLineHeight = textmetric.tmExternalLeading + textmetric.tmHeight;
rect.left = GetDeviceCaps(hDC, LOGPIXELSX) / 4; /* 1/4 inch */
rect.right = GetDeviceCaps(hDC, HORZRES);
rect.top = GetDeviceCaps(hDC, LOGPIXELSY) / 4; /* 1/4 inch */
rect.bottom = rect.top + nLineHeight;
rectMouse = rect;
rect.top += nLineHeight;
rect.bottom += nLineHeight;
rectButton = rect;
rect.top += nLineHeight;
rect.bottom += nLineHeight;
rectKeyboard = rect;
rect.top += nLineHeight;
rect.bottom += nLineHeight;
rectCharacter = rect;
rect.top += nLineHeight;
rect.bottom += nLineHeight;
rectScroll = rect;
rect.top += nLineHeight;
rect.bottom += nLineHeight;
rectTimer = rect;
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return (TRUE);
}
/****************************************************************************
FUNCTION: MainWndProc(HWND, unsigned, WORD, LONG)
PURPOSE: Processes messages
MESSAGES:
WM_COMMAND - application menu (About dialog box)
WM_CREATE - create window
WM_MOUSEMOVE - mouse movement
WM_LBUTTONDOWN - left mouse button pressed
WM_LBUTTONUP - left mouse button released
WM_LBUTTONDBLCLK - left mouse button double clicked
WM_KEYDOWN - key pressed
WM_KEYUP - key released
WM_CHAR - ASCII character received
WM_TIMER - timer has elapsed
WM_HSCROLL - mouse click in horizontal scroll bar
WM_VSCROLL - mouse click in vertical scroll bar
WM_PAINT - update window, draw objects
WM_DESTROY - destroy window
COMMENTS:
This demonstrates how input messages are received, and what the
additional information is that comes with the message.
****************************************************************************/
long FAR PASCAL MainWndProc(hWnd, message, wParam, lParam)
HWND hWnd;
unsigned message;
WORD wParam;
LONG lParam;
{
FARPROC lpProcAbout;
HDC hDC; /* display-context variable */
PAINTSTRUCT ps; /* paint structure */
char HorzOrVertText[12];
char ScrollTypeText[20];
RECT rect;
switch (message) {
case WM_COMMAND:
if (wParam == IDM_ABOUT) {
lpProcAbout = MakeProcInstance(About, hInst);
DialogBox(hInst,
"AboutBox",
hWnd,
lpProcAbout);
FreeProcInstance(lpProcAbout);
break;
}
else
return (DefWindowProc(hWnd, message, wParam, lParam));
case WM_CREATE:
/* Set the timer for five-second intervals */
idTimer = SetTimer(hWnd, NULL, 5000, (FARPROC) NULL);
break;
case WM_MOUSEMOVE:
wsprintf(MouseText, "WM_MOUSEMOVE: %x, %d, %d",
wParam, LOWORD(lParam), HIWORD(lParam));
InvalidateRect(hWnd, &rectMouse, TRUE);
break;
case WM_LBUTTONDOWN:
wsprintf(ButtonText, "WM_LBUTTONDOWN: %x, %d, %d",
wParam, LOWORD(lParam), HIWORD(lParam));
InvalidateRect(hWnd, &rectButton, TRUE);
break;
case WM_LBUTTONUP:
wsprintf(ButtonText, "WM_LBUTTONUP: %x, %d, %d",
wParam, LOWORD(lParam), HIWORD(lParam));
InvalidateRect(hWnd, &rectButton, TRUE);
break;
case WM_LBUTTONDBLCLK:
wsprintf(ButtonText, "WM_LBUTTONDBLCLK: %x, %d, %d",
wParam, LOWORD(lParam), HIWORD(lParam));
InvalidateRect(hWnd, &rectButton, TRUE);
break;
case WM_KEYDOWN:
wsprintf(KeyboardText, "WM_KEYDOWN: %x, %x, %x",
wParam, LOWORD(lParam), HIWORD(lParam));
InvalidateRect(hWnd, &rectKeyboard, TRUE);
break;
case WM_KEYUP:
wsprintf(KeyboardText, "WM_KEYUP: %x, %x, %x",
wParam, LOWORD(lParam), HIWORD(lParam));
InvalidateRect(hWnd, &rectKeyboard, TRUE);
break;
case WM_CHAR:
wsprintf(CharacterText, "WM_CHAR: %c, %x, %x",
wParam, LOWORD(lParam), HIWORD(lParam));
InvalidateRect(hWnd, &rectCharacter, TRUE);
break;
case WM_TIMER:
wsprintf(TimerText, "WM_TIMER: %d seconds",
nTimerCount += 5);
InvalidateRect(hWnd, &rectTimer, TRUE);
break;
case WM_HSCROLL:
case WM_VSCROLL:
strcpy(HorzOrVertText,
(message == WM_HSCROLL) ? "WM_HSCROLL" : "WM_VSCROLL");
strcpy(ScrollTypeText,
(wParam == SB_LINEUP) ? "SB_LINEUP" :
(wParam == SB_LINEDOWN) ? "SB_LINEDOWN" :
(wParam == SB_PAGEUP) ? "SB_PAGEUP" :
(wParam == SB_PAGEDOWN) ? "SB_PAGEDOWN" :
(wParam == SB_THUMBPOSITION) ? "SB_THUMBPOSITION" :
(wParam == SB_THUMBTRACK) ? "SB_THUMBTRACK" :
(wParam == SB_ENDSCROLL) ? "SB_ENDSCROLL" : "unknown");
wsprintf(ScrollText, "%s: %s, %x, %x",
(LPSTR)HorzOrVertText,
(LPSTR)ScrollTypeText,
LOWORD(lParam),
HIWORD(lParam));
InvalidateRect(hWnd, &rectScroll, TRUE);
break;
case WM_PAINT:
hDC = BeginPaint (hWnd, &ps);
if (IntersectRect(&rect, &rectMouse, &ps.rcPaint))
TextOut(hDC, rectMouse.left, rectMouse.top,
MouseText, strlen(MouseText));
if (IntersectRect(&rect, &rectButton, &ps.rcPaint))
TextOut(hDC, rectButton.left, rectButton.top,
ButtonText, strlen(ButtonText));
if (IntersectRect(&rect, &rectKeyboard, &ps.rcPaint))
TextOut(hDC, rectKeyboard.left, rectKeyboard.top,
KeyboardText, strlen(KeyboardText));
if (IntersectRect(&rect, &rectCharacter, &ps.rcPaint))
TextOut(hDC, rectCharacter.left, rectCharacter.top,
CharacterText, strlen(CharacterText));
if (IntersectRect(&rect, &rectTimer, &ps.rcPaint))
TextOut(hDC, rectTimer.left, rectTimer.top,
TimerText, strlen(TimerText));
if (IntersectRect(&rect, &rectScroll, &ps.rcPaint))
TextOut(hDC, rectScroll.left, rectScroll.top,
ScrollText, strlen(ScrollText));
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
KillTimer(hWnd, idTimer); /* Stops the timer
PostQuitMessage(0);
break;
default:
return (DefWindowProc(hWnd, message, wParam, lParam));
}
return (NULL);
}
/****************************************************************************
FUNCTION: About(HWND, unsigned, WORD, LONG)
PURPOSE: Processes messages for "About" dialog box
MESSAGES:
WM_INITDIALOG - initialize dialog box
WM_COMMAND - Input received
****************************************************************************/
BOOL FAR PASCAL About(hDlg, message, wParam, lParam)
HWND hDlg;
unsigned message;
WORD wParam;
LONG lParam;
{
switch (message) {
case WM_INITDIALOG:
return (TRUE);
case WM_COMMAND:
if (wParam == IDOK) {
EndDialog(hDlg, TRUE);
return (TRUE);
}
break;
}
return (FALSE);
}
MEMORY1.C
CD-ROM Disc Path: \SAMPCODE\WIN_SDK\MEMORY\MEMORY1.C
#include "windows.h"
#include "memory.h"
HANDLE hInst;
/****************************************************************************
MODULE: memory1.c
FUNCTION: WinMain(HANDLE, HANDLE, LPSTR, int)
PURPOSE: calls initialization function, processes message loop
****************************************************************************/
int PASCAL WinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow)
HANDLE hInstance;
HANDLE hPrevInstance;
LPSTR lpCmdLine;
int nCmdShow;
{
MSG msg;
if (!hPrevInstance)
if (!InitApplication(hInstance))
return (FALSE);
if (!InitInstance(hInstance, nCmdShow))
return (FALSE);
while (GetMessage(&msg, NULL, NULL, NULL)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (msg.wParam);
}
MEMORY2.C
CD-ROM Disc Path: \SAMPCODE\WIN_SDK\MEMORY\MEMORY2.C
#include "windows.h"
#include "memory.h"
/****************************************************************************
MODULE: memory2.c
FUNCTION: MemoryInit(HANDLE)
PURPOSE: Initializes window data and registers window class
****************************************************************************/
BOOL InitApplication(hInstance)
HANDLE hInstance;
{
WNDCLASS wc;
wc.style = NULL;
wc.lpfnWndProc = MainWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = "MemoryMenu";
wc.lpszClassName = "MemoryWClass";
return (RegisterClass(&wc));
}
/****************************************************************************
MODULE: memory3.c
FUNCTION: InitInstance(HANDLE, int)
PURPOSE: Saves instance handle and creates main window
****************************************************************************/
BOOL InitInstance(hInstance, nCmdShow)
HANDLE hInstance;
int nCmdShow;
{
HWND hwnd;
hInst = hInstance;
hwnd = CreateWindow(
"MemoryWClass",
"Memory Sample Application",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
hInstance,
NULL
);
if (!hwnd)
return (FALSE);
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
return (TRUE);
}
MEMORY3.C
CD-ROM Disc Path: \SAMPCODE\WIN_SDK\MEMORY\MEMORY3.C
#include "windows.h"
#include "memory.h"
/****************************************************************************
MODULE: memory3.c
FUNCTION: MainWndProc(HWND, unsigned, WORD, LONG)
PURPOSE: Processes messages
MESSAGES:
WM_COMMAND - application menu (About dialog box)
WM_DESTROY - destroy window
****************************************************************************/
long FAR PASCAL MainWndProc(hWnd, message, wParam, lParam)
HWND hWnd;
unsigned message;
WORD wParam;
LONG lParam;
{
FARPROC lpProcAbout;
switch (message) {
case WM_COMMAND:
if (wParam == IDM_ABOUT) {
lpProcAbout = MakeProcInstance(About, hInst);
DialogBox(hInst,
"AboutBox",
hWnd,
lpProcAbout);
FreeProcInstance(lpProcAbout);
break;
}
else
return (DefWindowProc(hWnd, message, wParam, lParam));
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return (DefWindowProc(hWnd, message, wParam, lParam));
}
return (NULL);
}
MEMORY4.C
CD-ROM Disc Path: \SAMPCODE\WIN_SDK\MEMORY\MEMORY4.C
#include "windows.h"
#include "memory.h"
/****************************************************************************
MODULE: memory4.c
FUNCTION: About(HWND, unsigned, WORD, LONG)
PURPOSE: Processes messages for "About" dialog box
MESSAGES:
WM_INITDIALOG - initialize dialog box
WM_COMMAND - Input received
****************************************************************************/
BOOL FAR PASCAL About(hDlg, message, wParam, lParam)
HWND hDlg;
unsigned message;
WORD wParam;
LONG lParam;
{
switch (message) {
case WM_INITDIALOG:
return (TRUE);
case WM_COMMAND:
if (wParam == IDOK
|| wParam == IDCANCEL) {
EndDialog(hDlg, TRUE);
return (TRUE);
}
break;
}
return (FALSE);
}
MENU.C
CD-ROM Disc Path: \SAMPCODE\WIN_SDK\MENU\MENU.C
/***************************************************************************
* *
* PROGRAM : Menu.c *
* *
* PURPOSE : To give a demonstration of the use of popup menus, user *
* defined menus and menu functions. *
* *
* FUNCTIONS : WinMain() - Calls the initialization function *
* and enters the message loop. *
* *
* MenuInit() - Registers the app. window class. *
* *
* About() - Dialog function for the About.. *
* dialog. *
* *
* ShrinkBitmap() - Shrinks a 64x64 bitmap to a size *
* useable for a user-defined menu *
* checkmark. *
* *
* HandleCreate() - Creates a new menu and appends it *
* to the main menu *
* *
* HandlePaint() - Handles repainting the app's client*
* area *
* *
* HandleChangeColors()- Changes the state of the "colors" *
* menu item. *
* *
* HandleDrawItem() - Redraws the menu items in the *
* "colors" menu *
* *
* HandlePopupMenu() - handles display of the "floating" *
* popup. *
* *
* MenuWndProc() - Window function for the app. *
* *
* *
***************************************************************************/
#include "windows.h"
#include "menu.h"
HANDLE hInst;
HMENU hBigMenu;
HBITMAP hbmCheckOn;
HBITMAP hbmCheckOff;
/****************************************************************************
* *
* FUNCTION : WinMain(HANDLE, HANDLE, LPSTR, int) *
* *
* PURPOSE : Creates the main app. window, calls an initialization *
* function and enters the message loop. *
* *
****************************************************************************
int PASCAL WinMain (hInstance, hPrevInstance, lpCmdLine, nCmdShow)
HANDLE hInstance, hPrevInstance;
LPSTR lpCmdLine;
int nCmdShow;
{
HWND hWnd;
MSG msg;
/* Register main window class if this is the first instance of the app. *
if (!hPrevInstance)
if (!MenuInit (hInstance))
return NULL;
hInst = hInstance;
/* Create the app. window */
hWnd = CreateWindow ("menu",
"Menu Example",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
(HWND) NULL,
NULL,
hInstance,
(LPSTR) NULL);
if (!hWnd)
return NULL;
ShowWindow (hWnd, nCmdShow);
UpdateWindow (hWnd);
while (GetMessage (&msg, NULL, NULL, NULL)){
/* Since we have no accelerators, no need to call
* TranslateAccelerator here.
*/
TranslateMessage (&msg);
DispatchMessage (&msg);
}
return(msg.wParam);
}
/****************************************************************************
* *
* FUNCTION : MenuInit (hInstance) *
* *
* PURPOSE : Registers the main window class. *
* *
* RETURNS : TRUE - if RegisterClass() went off ok *
* FALSE - otherwise. *
* *
****************************************************************************
BOOL NEAR PASCAL MenuInit (hInstance)
HANDLE hInstance;
{
HANDLE hMemory;
PWNDCLASS pWndClass;
BOOL bSuccess;
/* Initialize the menu window class */
hMemory = LocalAlloc(LPTR, sizeof(WNDCLASS));
pWndClass = (PWNDCLASS) LocalLock(hMemory);
pWndClass->style = NULL;
pWndClass->lpfnWndProc = MenuWndProc;
pWndClass->hInstance = hInstance;
pWndClass->hIcon = LoadIcon (hInstance, "menu");
pWndClass->hCursor = LoadCursor (NULL, IDC_ARROW);
pWndClass->hbrBackground = GetStockObject (WHITE_BRUSH);
pWndClass->lpszMenuName = (LPSTR) "MenuMenu",
pWndClass->lpszClassName = (LPSTR) "menu";
bSuccess = RegisterClass (pWndClass);
LocalUnlock (hMemory);
LocalFree (hMemory);
return bSuccess;
}
/****************************************************************************
* *
* FUNCTION : About (hDlg, message, wParam, lParam) *
* *
* PURPOSE : Dialog function for the About menu... dialog. *
* *
****************************************************************************
BOOL FAR PASCAL About(hDlg, message, wParam, lParam)
HWND hDlg;
unsigned message;
WORD wParam;
LONG lParam;
{
switch (message){
case WM_INITDIALOG:
return(TRUE);
case WM_COMMAND:
if (wParam == IDOK){
EndDialog(hDlg,NULL);
return(TRUE);
}
break;
}
return(FALSE);
}
/****************************************************************************
* *
* FUNCTION : ShrinkBitmap(hwnd, hbm) *
* *
* PURPOSE : This function shrinks a 64x64 bitmap into a bitmap useable *
* for the user-defined checkmark for menu items. This can be *
* easily generalized to shrink bitmaps of any size. *
* *
* RETURNS : HBITMAP - A handle to the new bitmap. *
* *
****************************************************************************
HBITMAP FAR PASCAL ShrinkBitmap (hwnd, hbm)
HWND hwnd;
HBITMAP hbm;
{
HDC hdc;
HDC hmemorydcNew;
HDC hmemorydcOld;
LONG checkMarkSize;
HBITMAP hCheckBitmap;
HBITMAP hOldBitmapSave;
HBITMAP hNewBitmapSave;
hdc = GetDC (hwnd);
/* Create DCs for the source (old) and target (new) bitmaps */
hmemorydcNew = CreateCompatibleDC (hdc);
hmemorydcOld = CreateCompatibleDC (hdc);
/* Determine the dimensions of the default menu checkmark and
* create a target bitmap of the same dimensions
*/
checkMarkSize = GetMenuCheckMarkDimensions ();
hCheckBitmap = CreateCompatibleBitmap (hdc,
LOWORD (checkMarkSize),
HIWORD (checkMarkSize));
/* Select the source bitmap and the target bitmap into their
* respective DCs.
*/
hOldBitmapSave = SelectObject (hmemorydcNew, hCheckBitmap);
hNewBitmapSave = SelectObject (hmemorydcOld, hbm);
/* Shrink the source bitmap into the target DC */
StretchBlt (hmemorydcNew,
0,
0,
LOWORD(checkMarkSize),
HIWORD(checkMarkSize),
hmemorydcOld,
0,
0,
64,
64,
SRCCOPY);
/* De-select the bitmaps and clean up .. */
SelectObject (hmemorydcNew, hOldBitmapSave);
SelectObject (hmemorydcOld, hNewBitmapSave);
DeleteDC (hmemorydcNew);
DeleteDC (hmemorydcOld);
ReleaseDC (hwnd, hdc);
/* .. and return a handle to the target bitmap */
return hCheckBitmap;
}
/****************************************************************************
* *
* FUNCTION : HandleCreate ( hwnd ) *
* *
* PURPOSE : Creates a new (empty) menu and appends to it the "State" *
* menu items. It sets up the user-defined checkmarks for the *
* menu. It then inserts this menu into the main menu bar. *
* *
****************************************************************************
void FAR PASCAL HandleCreate (hwnd)
HWND hwnd;
{
HMENU hMenu;
HMENU hWndMenu;
HBITMAP hbmOn;
HBITMAP hbmOff;
/* Create a new menu into the menubar on the fly */
hMenu = CreateMenu ();
if (!hMenu)
return;
/* Append the state menu items to it */
AppendMenu (hMenu, MF_STRING, IDM_STATE1, "South Dakota");
AppendMenu (hMenu, MF_STRING, IDM_STATE2, "Washington");
AppendMenu (hMenu, MF_STRING, IDM_STATE3, "California");
if (!AppendMenu (hMenu, MF_STRING, IDM_STATE4, "Oregon")){
/* It is unlikely the other appends will fail and this will succeed.
* So just check this one. And if it fails, Destroy the menu for
* good measure and return.
*/
DestroyMenu(hMenu);
return;
}
hbmCheckOn = ShrinkBitmap (hwnd, LoadBitmap (hInst, "checkon"));
hbmCheckOff = ShrinkBitmap (hwnd, LoadBitmap (hInst, "checkoff"));
/* Set up the user-defined check marks */
SetMenuItemBitmaps (hMenu, 0, MF_BYPOSITION, hbmCheckOff, hbmCheckOn);
SetMenuItemBitmaps (hMenu, 1, MF_BYPOSITION, hbmCheckOff, hbmCheckOn);
SetMenuItemBitmaps (hMenu, 2, MF_BYPOSITION, hbmCheckOff, hbmCheckOn);
SetMenuItemBitmaps (hMenu, 3, MF_BYPOSITION, hbmCheckOff, hbmCheckOn);
/* Now insert the menu into the main menu bar. */
hWndMenu = GetMenu (hwnd);
InsertMenu (hWndMenu, 2, MF_POPUP|MF_BYPOSITION, (WORD)hMenu, "States");
return;
}
/****************************************************************************
* *
* FUNCTION : HandlePaint ( hwnd ) *
* *
* PURPOSE : Handles the repainting of the main app's client area. *
* *
****************************************************************************
void FAR PASCAL HandlePaint (hwnd)
HWND hwnd;
{
HDC hdc;
PAINTSTRUCT ps;
RECT rc;
hdc = BeginPaint (hwnd, (LPPAINTSTRUCT)&ps);
/* Center the text in the client area */
GetClientRect (hwnd, (LPRECT)&rc);
DrawText (hdc,
"Down click in the window for a popup menu",
41,
(LPRECT)&rc,
DT_CENTER | DT_WORDBREAK);
EndPaint(hwnd, (LPPAINTSTRUCT)&ps);
}
/****************************************************************************
* *
* FUNCTION : HandleChangeColors (hwnd) *
* *
* PURPOSE : Toggles the state of the Owner Draw item in the Colors *
* menu. If it is on, the "Black", "Blue", "Red", and "Green" *
* individual menu text items are modified so that they will *
* contain bands of color. Otherwise, the colors are replaced *
* by the text. *
* *
****************************************************************************
void FAR PASCAL HandleChangeColors(hwnd)
HWND hwnd;
{
HMENU hMenu;
BOOL fOwnerDraw;
/* Get a handle to the Colors menu. This is at position 1. */
hMenu = GetSubMenu (GetMenu (hwnd), IDCOLORS_POS);
/* Get the current state of the item */
fOwnerDraw = GetMenuState ( hMenu,
IDM_COLOROWNERDR, MF_BYCOMMAND) & MF_CHECKED;
/* Toggle the state of the item. */
CheckMenuItem ( hMenu,
IDM_COLOROWNERDR,
MF_BYCOMMAND | (fOwnerDraw ? MF_UNCHECKED : MF_CHECKED));
if (!fOwnerDraw){
/* Change the items to owner-draw items. Pass the RGB value for the
* color as the application-supplied data. This makes it easier for
* us to draw the items.
*/
ModifyMenu(hMenu,
IDM_BLACK,
MF_OWNERDRAW | MF_BYCOMMAND,
IDM_BLACK,
(LPSTR)RGB (0,0,0));
ModifyMenu(hMenu,
IDM_BLUE,
MF_OWNERDRAW | MF_BYCOMMAND,
IDM_BLUE,
(LPSTR)RGB (0,0,255));
ModifyMenu(hMenu,
IDM_RED,
MF_OWNERDRAW | MF_BYCOMMAND,
IDM_RED,
(LPSTR)RGB (255,0,0));
ModifyMenu(hMenu,
IDM_GREEN,
MF_OWNERDRAW | MF_BYCOMMAND,
IDM_GREEN,
(LPSTR)RGB (0,255,0));
}
else {
/* Change the items to normal text items. */
ModifyMenu(hMenu, IDM_BLACK, MF_BYCOMMAND, IDM_BLACK, "Black");
ModifyMenu(hMenu, IDM_BLUE, MF_BYCOMMAND, IDM_BLUE, "Blue");
ModifyMenu(hMenu, IDM_RED, MF_BYCOMMAND, IDM_RED, "Red");
ModifyMenu(hMenu, IDM_GREEN, MF_BYCOMMAND, IDM_GREEN, "Green");
}
}
/****************************************************************************
* *
* FUNCTION : HandleDrawItem ( hwnd, lpdis) *
* *
* PURPOSE : Called in response to a WM_DRAWITEM message, i.e. when the *
* colors menu is being modified to an owner-draw menu, or *
* one of the items is selected. It sizes the checkmark bitmap*
* to fit next to a color band and draws the color bands and *
* the checkmark on the popup menu. *
* *
****************************************************************************
void FAR PASCAL HandleDrawItem(hwnd, lpdis)
HWND hwnd;
LPDRAWITEMSTRUCT lpdis;
{
HDC hdcBitmap;
HBITMAP hbmSave;
HBRUSH hbr;
RECT rc;
LONG checkMarkSize;
DWORD textColorSave;
DWORD bkColorSave;
/* Get the size of the checkmark so we can leave room for it since we
* want to be able to check the selected color.
*/
checkMarkSize = GetMenuCheckMarkDimensions ();
if (lpdis->itemAction == ODA_SELECT ||
lpdis->itemAction == ODA_DRAWENTIRE){
CopyRect ((LPRECT)&rc, (LPRECT)&lpdis->rcItem);
InflateRect ((LPRECT)&rc, (-2 - LOWORD(checkMarkSize)), -2);
if (lpdis->itemState & ODS_SELECTED)
{
/* Item has been selected -- hilite with a gray frame */
hbr = GetStockObject (GRAY_BRUSH);
FrameRect (lpdis->hDC, (LPRECT)&rc, hbr);
}
else if (lpdis->itemAction == ODA_SELECT)
{
/* Item has been de-selected -- remove gray frame */
hbr = CreateSolidBrush (GetSysColor (COLOR_MENU));
FrameRect (lpdis->hDC, (LPRECT)&rc, hbr);
DeleteObject (hbr);
}
}
if (lpdis->itemAction == ODA_DRAWENTIRE){
/* Paint the color item in the color requested. */
hbr = CreateSolidBrush (lpdis->itemData);
CopyRect ((LPRECT)&rc, (LPRECT)&lpdis->rcItem);
InflateRect ((LPRECT)&rc, -10-LOWORD(checkMarkSize), -10);
FillRect (lpdis->hDC, (LPRECT)&rc, hbr);
DeleteObject (hbr);
if (lpdis->itemState & ODS_CHECKED){
/* Draw the check mark if the item is checked. */
hdcBitmap = CreateCompatibleDC (lpdis->hDC);
hbmSave = SelectObject (hdcBitmap, hbmCheckOn);
textColorSave = SetTextColor (lpdis->hDC, 0x00000000L);
bkColorSave = SetBkColor (lpdis->hDC, 0x00FFFFFFL);
/* Use Magic bitblt op so that monochrome bitmaps preserve
background and foreground colors. */
BitBlt (lpdis->hDC,
lpdis->rcItem.left,
lpdis->rcItem.top+
(MEASUREITEMHEIGHT - HIWORD (checkMarkSize)) / 2,
LOWORD (checkMarkSize),
HIWORD (checkMarkSize),
hdcBitmap,
0,
0,
ROP_PSDPxax);
/* Restore colors and bitmap and clean up */
SetTextColor (lpdis->hDC, textColorSave);
SetBkColor (lpdis->hDC, bkColorSave);
SelectObject (hdcBitmap, hbmSave);
DeleteDC (hdcBitmap);
}
}
}
/****************************************************************************
* *
* FUNCTION : HandlePopupMenu (hwnd, point) *
* *
* PURPOSE : Handles the display of the "floating" popup that appears *
* on a mouse click in the app's client area. *
* *
****************************************************************************
void FAR PASCAL HandlePopupMenu (hwnd, point)
HWND hwnd;
POINT point;
{
HMENU hMenu;
HMENU hMenuTrackPopup;
/* Get the menu for the popup from the resource file. */
hMenu = LoadMenu (hInst, "PopupMenu");
if (!hMenu)
return;
/* Get the first menu in it which we will use for the call to
* TrackPopup(). This could also have been created on the fly using
* CreatePopupMenu and then we could have used InsertMenu() or
* AppendMenu.
*/
hMenuTrackPopup = GetSubMenu (hMenu, 0);
/* Convert the mouse point to screen coordinates since that is what
* TrackPopup expects.
*/
ClientToScreen (hwnd, (LPPOINT)&point);
/* Draw and track the "floating" popup */
TrackPopupMenu (hMenuTrackPopup, 0, point.x, point.y, 0, hwnd, NULL);
/* Destroy the menu since were are done with it. */
DestroyMenu (hMenu);
}
/****************************************************************************
* *
* FUNCTION : MenuWndProc (hWnd, message, wParam, lParam) *
* *
* PURPOSE : Window function for the main app. window. Processes all the*
* menu selections and oter messages. *
* *
****************************************************************************
long FAR PASCAL MenuWndProc (hWnd, message, wParam, lParam)
HWND hWnd;
unsigned message;
WORD wParam;
LONG lParam;
{
FARPROC lpProc;
HMENU hMenu;
LPDRAWITEMSTRUCT dis;
RECT rc;
switch (message){
case WM_SYSCOMMAND:
/* Show the About ... dialog */
if (wParam == ID_ABOUT){
lpProc = MakeProcInstance (About, hInst);
DialogBox (hInst,
"AboutBox",
hWnd,
lpProc);
FreeProcInstance (lpProc);
break;
}
else
return DefWindowProc (hWnd, message, wParam, lParam);
case WM_COMMAND:
switch (wParam){
case IDM_EXIT:
DestroyWindow (hWnd);
break;
case IDM_ABOUT:
/* Bring up the About.. dialog box */
lpProc = MakeProcInstance (About, hInst);
DialogBox (hInst,
"AboutBox",
hWnd,
lpProc);
FreeProcInstance (lpProc);
break;
case IDM_COLOROWNERDR:
/* Change colors in color menu depending on state of this
menu item. */
HandleChangeColors (hWnd);
break;
case IDM_STATE1:
case IDM_STATE2:
case IDM_STATE3:
case IDM_STATE4:
/* Get a handle to the states menu... */
hMenu = GetSubMenu (GetMenu (hWnd), IDSTATES_POS);
/* Uncheck all the items. */
CheckMenuItem (hMenu, IDM_STATE1,
MF_BYCOMMAND | MF_UNCHECKED);
CheckMenuItem (hMenu, IDM_STATE2,
MF_BYCOMMAND | MF_UNCHECKED);
CheckMenuItem (hMenu, IDM_STATE3,
MF_BYCOMMAND | MF_UNCHECKED);
CheckMenuItem (hMenu, IDM_STATE4,
MF_BYCOMMAND | MF_UNCHECKED);
/* ...and just check the selected one.*/
CheckMenuItem (hMenu, wParam,
MF_BYCOMMAND | MF_CHECKED);
break;
case IDM_BLACK:
case IDM_RED:
case IDM_BLUE:
case IDM_GREEN:
/* Get a handle to the Colors menu. */
hMenu = GetSubMenu (GetMenu (hWnd),IDCOLORS_POS);
/* Uncheck all the items. */
CheckMenuItem (hMenu, IDM_BLACK,
MF_BYCOMMAND | MF_UNCHECKED);
CheckMenuItem (hMenu, IDM_RED,
MF_BYCOMMAND | MF_UNCHECKED);
CheckMenuItem (hMenu, IDM_BLUE,
MF_BYCOMMAND | MF_UNCHECKED);
CheckMenuItem (hMenu, IDM_GREEN,
MF_BYCOMMAND | MF_UNCHECKED);
/* ...and just check the selected one.*/
CheckMenuItem (hMenu, wParam,
MF_BYCOMMAND | MF_CHECKED);
break;
case IDM_FONT:
/* Messages sent to us from TrackPopupMenu when
* items are selected from the "floating" popups
*/
MessageBox (hWnd,
"A font was selected",
"Popup Menu Alert",
MB_APPLMODAL|MB_OK);
break;
case IDM_SIZE:
MessageBox (hWnd,
"A size was selected",
"Popup Menu Alert",
MB_APPLMODAL|MB_OK);
break;
case IDM_STYLE:
MessageBox (hWnd,
"A style was selected",
"Popup Menu Alert",
MB_APPLMODAL|MB_OK);
break;
}
break;
case WM_SIZE:
if (lParam){
/* If window is being sized to a non zero value...
* invalidate it's client area.
*/
InvalidateRect (hWnd, NULL, TRUE);
}
break;
case WM_PAINT:
HandlePaint (hWnd);
break;
case WM_MEASUREITEM:
/* Use the same width for all items. We could examine the item id
and use different widths/heights for each item. */
((LPMEASUREITEMSTRUCT)lParam)->itemWidth = MEASUREITEMWIDTH;
((LPMEASUREITEMSTRUCT)lParam)->itemHeight = MEASUREITEMHEIGHT;
return TRUE;
case WM_DRAWITEM:
/* Redraw the "colors" menu in normal/ownerdrawmode */
HandleDrawItem (hWnd,(LPDRAWITEMSTRUCT)lParam);
return TRUE;
break;
case WM_CREATE:
/* Create the menu */
HandleCreate (hWnd);
break;
case WM_DESTROY:
/* Delete the on/off bitmaps so that they don't waste memory. */
DeleteObject (hbmCheckOn);
DeleteObject (hbmCheckOff);
PostQuitMessage (0);
break;
case WM_LBUTTONDOWN:
/* Draw the "floating" popup in the app's client area */
GetClientRect (hWnd, (LPRECT)&rc);
if (PtInRect ((LPRECT)&rc, MAKEPOINT (lParam)))
HandlePopupMenu (hWnd, lParam);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return(NULL);
}
MPFILE.C
CD-ROM Disc Path: \SAMPCODE\WIN_SDK\MULTIPAD\MPFILE.C
/***************************************************************************
* *
* MODULE : MpFile.c *
* *
* PURPOSE : Contains the code for File I/O for Multipad. *
* *
* FUNCTIONS : AlreadyOpen - Determines if a file is already open. *
* *
* AddFile - Creates a new MDI window and, if specified,*
* loads a file into it. *
* *
* LoadFile - Loads a file into a MDI window. *
* *
* ReadFile - Calls File/Open dialog and appropriately *
* responds to the user's input. *
* *
* SaveFile - Saves the contents of a MDI window's edit *
* control to a file. *
* *
* SetSaveFrom - Formats the "Save 'file' to" string. *
* *
* SaveAsDlgProc - Dialog function for the File/SaveAs dialog.*
* *
* ChangeFile - Calls File/SaveAs dialog. *
* *
***************************************************************************/
#include "multipad.h"
VOID NEAR PASCAL GetFileName(PSTR);
int FAR PASCAL DialogBoxParam(HANDLE,LPSTR,HWND,FARPROC,LONG);
OFSTRUCT of;
/****************************************************************************
* *
* FUNCTION : AlreadyOpen(szFile) *
* *
* PURPOSE : Checks to see if the file described by the string pointed *
* to by 'szFile' is already open. *
* *
* RETURNS : a handle to the described file's window if that file is *
* already open; NULL otherwise. *
* *
****************************************************************************
HWND AlreadyOpen(char *szFile)
{
int iDiff;
HWND hwndCheck;
char szChild[64];
LPSTR lpChild, lpFile;
int wFileTemp;
/* Open the file with the OF_PARSE flag to obtain the fully qualified
* pathname in the OFSTRUCT structure.
*/
wFileTemp = OpenFile ((LPSTR)szFile, (LPOFSTRUCT)&of, OF_PARSE);
if (! wFileTemp)
return(NULL);
_lclose (wFileTemp);
/* Check each MDI child window in Multipad */
for ( hwndCheck = GetWindow(hwndMDIClient, GW_CHILD);
hwndCheck;
hwndCheck = GetWindow(hwndCheck, GW_HWNDNEXT) ) {
/* Initialization for comparison */
lpChild = szChild;
lpFile = AnsiUpper((LPSTR) of.szPathName);
iDiff = 0;
/* Skip icon title windows */
if (GetWindow(hwndCheck, GW_OWNER))
continue;
/* Get current child window's name */
GetWindowText(hwndCheck, lpChild, 64);
/* Compare window name with given name */
while ((*lpChild) && (*lpFile) && (!iDiff)){
if (*lpChild++ != *lpFile++)
iDiff = 1;
}
/* If the two names matched, the file is already */
/* open -- return handle to matching child window. */
if (!iDiff)
return(hwndCheck);
}
/* No match found -- file is not open -- return NULL handle */
return(NULL);
}
/****************************************************************************
* *
* FUNCTION : AddFile (lpName) *
* *
* PURPOSE : Creates a new MDI window. If the lpName parameter is not *
* NULL, it loads a file into the window. *
* *
* RETURNS : HWND - A handle to the new window. *
* *
****************************************************************************
HWND FAR PASCAL AddFile(pName)
char * pName;
{
HWND hwnd;
char sz[160];
MDICREATESTRUCT mcs;
if (!pName) {
/* The pName parameter is NULL -- load the "Untitled" string from */
/* STRINGTABLE and set the title field of the MDI CreateStruct. */
LoadString (hInst, IDS_UNTITLED, sz, sizeof(sz));
mcs.szTitle = (LPSTR)sz;
}
else
/* Title the window with the fully qualified pathname obtained by
* calling OpenFile() with the OF_PARSE flag (in function
* AlreadyOpen(), which is called before AddFile().
*/
mcs.szTitle = of.szPathName;
mcs.szClass = szChild;
mcs.hOwner = hInst;
/* Use the default size for the window */
mcs.x = mcs.cx = CW_USEDEFAULT;
mcs.y = mcs.cy = CW_USEDEFAULT;
/* Set the style DWORD of the window to default */
mcs.style = styleDefault;
/* tell the MDI Client to create the child */
hwnd = (WORD)SendMessage (hwndMDIClient,
WM_MDICREATE,
0,
(LONG)(LPMDICREATESTRUCT)&mcs);
/* Did we get a file? Read it into the window */
if (pName){
if (!LoadFile(hwnd, pName)){
/* File couldn't be loaded -- close window */
SendMessage(hwndMDIClient, WM_MDIDESTROY, (WORD) hwnd, 0L);
}
}
return hwnd;
}
/****************************************************************************
* *
* FUNCTION : LoadFile (lpName) *
* *
* PURPOSE : Given the handle to a MDI window and a filename, reads the *
* file into the window's edit control child. *
* *
* RETURNS : TRUE - If file is sucessfully loaded. *
* FALSE - Otherwise. *
* *
****************************************************************************
int FAR PASCAL LoadFile (hwnd, pName)
HWND hwnd;
char * pName;
{
WORD wLength;
HANDLE hT;
LPSTR lpB;
HWND hwndEdit;
int fh;
hwndEdit = GetWindowWord (hwnd, GWW_HWNDEDIT);
/* The file has a title, so reset the UNTITLED flag. */
SetWindowWord(hwnd, GWW_UNTITLED, FALSE);
fh = _lopen (pName, 0);
/* Make sure file has been opened correctly */
if ( fh < 0 )
goto error;
/* Find the length of the file */
wLength = (WORD)_llseek (fh, 0L, 2);
_llseek (fh, 0L, 0);
/* Attempt to reallocate the edit control's buffer to the file size */
hT = (HANDLE)SendMessage (hwndEdit, EM_GETHANDLE, 0, 0L);
if (LocalReAlloc(hT, wLength+1, LHND) == NULL) {
/* Couldn't reallocate to new size -- error */
_lclose (fh);
goto error;
}
/* read the file into the buffer */
if (wLength != _lread (fh, (lpB = (LPSTR)LocalLock (hT)), wLength))
MPError (hwnd, MB_OK|MB_ICONHAND, IDS_CANTREAD, (LPSTR)pName);
/* Zero terminate the edit buffer */
lpB[wLength] = 0;
LocalUnlock (hT);
SendMessage (hwndEdit, EM_SETHANDLE, hT, 0L);
_lclose (fh);
return TRUE;
error:
/* Report the error and quit */
MPError(hwnd, MB_OK | MB_ICONHAND, IDS_CANTOPEN, (LPSTR)pName);
return FALSE;
}
/****************************************************************************
* *
* FUNCTION : ReadFile(hwnd) *
* *
* PURPOSE : Called in response to a File/Open menu selection. It asks *
* the user for a file name and responds appropriately. *
* *
****************************************************************************
VOID FAR PASCAL ReadFile(HWND hwnd)
{
char szFile[128];
HWND hwndFile;
GetFileName (szFile);
/* If the result is not the empty string -- take appropriate action */
if (*szFile) {
/* Is file already open?? */
if (hwndFile = AlreadyOpen(szFile)) {
/* Yes -- bring the file's window to the top */
BringWindowToTop(hwndFile);
}
else {
/* No -- make a new window and load file into it */
AddFile(szFile);
}
}
}
/****************************************************************************
* *
* FUNCTION : SaveFile (hwnd) *
* *
* PURPOSE : Saves contents of current edit control to disk. *
* *
****************************************************************************
VOID FAR PASCAL SaveFile( hwnd )
HWND hwnd;
{
HANDLE hT;
LPSTR lpT;
char szFile[128];
WORD cch;
int fh;
OFSTRUCT of;
HWND hwndEdit;
PSTR pch;
hwndEdit = GetWindowWord ( hwnd, GWW_HWNDEDIT);
GetWindowText (hwnd, szFile, sizeof(szFile));
/* If there is no extension (control is 'Untitled') add .TXT as extension
for (cch = FALSE, lpT = szFile; *lpT; lpT++)
switch (*lpT){
case '.':
cch = TRUE;
break;
case '\\':
case ':' :
cch = FALSE;
break;
}
if (!cch)
LoadString (hInst, IDS_ADDEXT, lpT, lpT - (LPSTR)szFile);
fh = OpenFile (szFile, &of, OF_WRITE | OF_CREATE);
/* If file could not be opened, quit */
if (fh < 0){
MPError (hwnd, MB_OK | MB_ICONHAND, IDS_CANTCREATE, (LPSTR)szFile);
return;
}
/* Find out the length of the text in the edit control */
cch = GetWindowTextLength (hwndEdit);
/* Obtain a handle to the text buffer */
hT = (HANDLE)SendMessage (hwndEdit, EM_GETHANDLE, 0, 0L);
lpT = (LPSTR)LocalLock (hT);
/* Write out the contents of the buffer to the file. */
if (cch != _lwrite (fh, lpT, cch))
MPError (hwnd, MB_OK | MB_ICONHAND, IDS_CANTWRITE, (LPSTR)szFile);
/* Clean up */
LocalUnlock (hT);
SendMessage (hwndEdit, EM_SETHANDLE, hT, 0L);
_lclose (fh);
return;
}
/****************************************************************************
* *
* FUNCTION : SetSaveFrom () *
* *
* PURPOSE : Formats the "Save 'file' to .." string. *
* *
****************************************************************************
VOID NEAR PASCAL SetSaveFrom ( hwnd , psz)
HWND hwnd;
PSTR psz;
{
char szFmt[32];
char szText[160];
/* The text string in the .RC file contains the format string... */
GetDlgItemText( hwnd, IDD_SAVEFROM, szFmt, sizeof(szFmt));
/* NOTE: this (LPSTR) cast MUST be here... wsprintf() is a cdecl
* (C calling conventions) function with varying args... there is
* no way for the compiler to know that all strings must be LPSTR's
* and do the conversion, so we have to be careful about wsprintf()'s.
*/
wsprintf ( szText, szFmt, (LPSTR)psz);
/* set the text in the static control */
SetDlgItemText (hwnd, IDD_SAVEFROM, szText);
}
/****************************************************************************
* *
* FUNCTION : SaveAsDlgProc(hwnd, message, wParam, lParam) *
* *
* PURPOSE : Dialog function File/SaveAs. It waits for a filename, and *
* then calls SaveFile or cancels the operation. *
* *
****************************************************************************
BOOL FAR PASCAL SaveAsDlgProc( hwnd, message, wParam, lParam)
HWND hwnd;
WORD message;
WORD wParam;
LONG lParam;
{
char sz[64];
char *pch;
BOOL fExt;
HWND hwndSave;
switch (message){
case WM_INITDIALOG:
/* Identify the window whose contents we're saving */
hwndSave = LOWORD (lParam);
/* Set it's name in the property list */
SetProp (hwnd, PROP_FILENAME, hwndSave);
GetWindowText (hwndSave, sz, sizeof(sz));
/* Set the save from string... */
SetSaveFrom (hwnd,sz);
/* Generate a filename complete with extension */
AnsiUpper (sz);
for (fExt = FALSE, pch = sz; *pch; pch++)
if (*pch == '.')
fExt = TRUE;
else if (*pch == '\\')
fExt = FALSE;
if (!fExt)
LoadString (hInst, IDS_ADDEXT, (LPSTR)pch, pch - sz);
/* Display the filename in the edit control */
SetDlgItemText (hwnd, IDD_SAVETO, sz);
/* Select the entire range of text */
SendDlgItemMessage (hwnd, IDD_SAVETO, EM_SETSEL, 0, MAKELONG (0,100));
DlgDirList (hwnd, "*.*", IDD_DIRS, IDD_PATH, ATTR_DIRS);
/* enable OK butto iff edit control is nonempty */
if (!*sz)
EnableWindow (GetDlgItem (hwnd, IDOK), FALSE);
break;
case WM_COMMAND:
switch (wParam){
case IDCANCEL:
/* Abort operation */
EndDialog(hwnd,1);
break;
case IDOK:
/* Just change the title of the MDI child. The calling
* function of ChangeFile(), which uses the title text
* for the filename, will do the actual save.
*/
hwndSave = GetProp (hwnd, PROP_FILENAME);
GetDlgItemText (hwnd, IDD_SAVETO, sz, sizeof(sz));
AnsiUpper ((LPSTR)sz);
SetWindowText (hwndSave, sz);
EndDialog (hwnd, 0);
break;
case IDD_SAVETO:
/* If the edit control changes, check to see if its empty.
* enable OK if it contains something
*/
if (HIWORD (lParam) != EN_CHANGE)
return FALSE;
EnableWindow (GetDlgItem (hwnd, IDOK),
(WORD) SendDlgItemMessage (hwnd,
IDD_SAVETO,
WM_GETTEXTLENGTH,
0,
0L));
break;
case IDD_DIRS:
if (HIWORD(lParam)==LBN_DBLCLK){
char szT[64];
DlgDirSelect ( hwnd, szT, IDD_DIRS);
lstrcat ( szT, "*.*");
DlgDirList (hwnd, szT, IDD_DIRS, IDD_PATH, ATTR_DIRS);
break;
}
return FALSE;
default:
return FALSE;
}
default:
return FALSE;
}
return TRUE;
}
/****************************************************************************
* *
* FUNCTION : ChangeFile (hwnd) *
* *
* PURPOSE : Invokes the File/SaveAs dialog. *
* *
* RETURNS : TRUE - if user selected OK or NO. *
* FALSE - otherwise. *
* *
****************************************************************************
BOOL FAR PASCAL ChangeFile (hwnd)
HWND hwnd;
{
FARPROC lpfn;
int i;
lpfn = MakeProcInstance (SaveAsDlgProc, hInst);
i = DialogBoxParam (hInst, IDD_SAVEAS, hwnd, lpfn, MAKELONG (hwnd, 0));
FreeProcInstance (lpfn);
if (!i)
SetWindowWord (hwnd, GWW_UNTITLED, 0);
return !i;
}
MPFIND.C
CD-ROM Disc Path: \SAMPCODE\WIN_SDK\MULTIPAD\MPFIND.C
/***************************************************************************
* *
* MODULE : MpFind.c *
* *
* PURPOSE : Code to do text searches in MultiPad. *
* *
* FUNCTIONS : RealSlowCompare () - Compares subject string with target *
* string. *
* *
* FindText () - Looks for the search string in the *
* active window. *
* *
* FindPrev () - Find previous occurence of search *
* string. *
* *
* FindNext () - Find next occurence of search string*
* *
* FindDlgProc () - Dialog function for Search/Find. *
* *
* Find () - Invokes FindDlgProc () *
* *
***************************************************************************/
#include "multipad.h"
#undef HIWORD
#undef LOWORD
#define HIWORD(l) (((WORD*)&(l))[1])
#define LOWORD(l) (((WORD*)&(l))[0])
BOOL fCase = FALSE; /* Turn case sensitivity off */
char szSearch[160] = ""; /* Initialize search string */
/****************************************************************************
* *
* FUNCTION : RealSlowCompare () *
* *
* PURPOSE : Compares subject string with the target string. This fn/ *
* is called repeatedly so that all substrings are compared, *
* which makes it O(n ** 2), hence it's name. *
* *
* RETURNS : TRUE - If pSubject is identical to pTarget. *
* FALSE - otherwise. *
* *
****************************************************************************
BOOL NEAR PASCAL RealSlowCompare (pSubject, pTarget )
register PSTR pSubject;
register PSTR pTarget;
{
if (fCase){
while (*pTarget)
if (*pTarget++ != *pSubject++)
return FALSE;
}
else{
/* If case-insensitive, convert both subject and target to lowercase
* before comparing.
*/
AnsiLower ((LPSTR)pTarget);
while (*pTarget)
if (*pTarget++ != (char)(DWORD)AnsiLower ((LPSTR)(DWORD)(BYTE)*pSubject
return FALSE;
}
return TRUE;
}
/****************************************************************************
* *
* FUNCTION : FindText () *
* *
* PURPOSE : Finds the search string in the active window according to *
* search direction (dch) specified ( -1 for reverse and 1 for*
* forward searches). *
* *
****************************************************************************
VOID NEAR PASCAL FindText( dch )
register int dch;
{
register PSTR pText;
HANDLE hT;
LONG l;
WORD cch;
int i;
if (!*szSearch)
return;
/* Find the current selection range */
l = SendMessage(hwndActiveEdit, EM_GETSEL, 0, 0L);
/* Get the handle to the text buffer and lock it */
hT = (HANDLE)SendMessage (hwndActiveEdit, EM_GETHANDLE, 0, 0L);
pText = LocalLock(hT);
/* Get the length of the text */
cch = (WORD)SendMessage (hwndActiveEdit, WM_GETTEXTLENGTH, 0, 0L);
/* Start with the next char. in selected range ... */
pText += LOWORD (l) + dch;
/* Compute how many characters are before/after the current selection*/
if (dch < 0)
i = LOWORD (l);
else
i = cch - LOWORD (l) + 1 - lstrlen (szSearch);
/* While there are uncompared substrings... */
while ( i > 0){
LOWORD(l)+=dch;
/* Does this substring match? */
if (RealSlowCompare(pText,szSearch)){
/* Yes, unlock the buffer.*/
LocalUnlock(hT);
/* Select the located string */
HIWORD(l) = LOWORD(l) + lstrlen (szSearch);
SendMessage (hwndActiveEdit, EM_SETSEL, 0, l);
return;
}
i--;
/* increment/decrement start position by 1 */
pText += dch;
}
/* Not found... unlock buffer. */
LocalUnlock (hT);
/* Give a message */
MPError (hwndFrame, MB_OK | MB_ICONEXCLAMATION, IDS_CANTFIND, (LPSTR)szSe
return;
}
/****************************************************************************
* *
* FUNCTION : FindPrev () *
* *
* PURPOSE : Finds the previous occurence of the search string. Calls *
* FindText () with a negative search direction. *
* *
****************************************************************************
VOID FAR PASCAL FindPrev(void)
{
FindText(-1);
}
/****************************************************************************
* *
* FUNCTION : FindNext () *
* *
* PURPOSE : Finds the next occurence of search string. Calls *
* FindText () with a positive search direction. *
* *
****************************************************************************
VOID FAR PASCAL FindNext(void)
{
FindText(1);
}
/****************************************************************************
* *
* FUNCTION : FindDlgProc(hwnd, message, wParam, lParam) *
* *
* PURPOSE : Dialog function for the Search/Find command. Prompts user *
* for target string, case flag and search direction. *
* *
****************************************************************************
BOOL FAR PASCAL FindDlgProc(hwnd, msg, wParam, lParam)
HWND hwnd;
WORD msg;
WORD wParam;
LONG lParam;
{
switch (msg){
case WM_INITDIALOG:{
/* Check/uncheck case button */
CheckDlgButton (hwnd, IDD_CASE, fCase);
/* Set default search string to most recently searched string */
SetDlgItemText (hwnd, IDD_SEARCH, szSearch);
/* Allow search only if target is nonempty */
if (!lstrlen (szSearch)){
EnableWindow (GetDlgItem (hwnd, IDOK), FALSE);
EnableWindow (GetDlgItem (hwnd, IDD_PREV), FALSE);
}
break;
}
case WM_COMMAND:{
/* Search forward by default (see IDOK below) */
int i = 1;
switch (wParam){
/* if the search target becomes non-empty, enable searching */
case IDD_SEARCH:
if (HIWORD (lParam) == EN_CHANGE){
if (!(WORD) SendDlgItemMessage (hwnd,
IDD_SEARCH,
WM_GETTEXTLENGTH,
0,
0L))
i = FALSE;
else
i = TRUE;
EnableWindow (GetDlgItem (hwnd, IDOK), i);
EnableWindow (GetDlgItem (hwnd, IDD_PREV), i);
}
break;
case IDD_CASE:
/* Toggle state of case button */
CheckDlgButton (hwnd,
IDD_CASE,
!IsDlgButtonChecked (hwnd, IDD_CASE));
break;
case IDD_PREV:
/* Set direction to backwards */
i=-1;
/*** FALL THRU ***/
case IDOK:
/* Save case selection */
fCase = IsDlgButtonChecked( hwnd, IDD_CASE);
/* Get search string */
GetDlgItemText (hwnd, IDD_SEARCH, szSearch, sizeof (szSearch));
/* Find the text */
FindText (i);
/*** FALL THRU ***/
/* End the dialog */
case IDCANCEL:
EndDialog (hwnd, 0);
break;
default:
return FALSE;
}
break;
}
default:
return FALSE;
}
return TRUE;
}
/****************************************************************************
* *
* FUNCTION : Find() *
* *
* PURPOSE : Invokes the Search/Find dialog. *
* *
****************************************************************************
VOID FAR PASCAL Find()
{
FARPROC lpfn;
lpfn = MakeProcInstance (FindDlgProc, hInst);
DialogBox (hInst, IDD_FIND, hwndFrame, lpfn);
FreeProcInstance (lpfn);
}
MPINIT.C
CD-ROM Disc Path: \SAMPCODE\WIN_SDK\MULTIPAD\MPINIT.C
/***************************************************************************
* *
* MODULE : MpInit.c *
* *
* PURPOSE : Contains initialization code for MultiPad. *
* *
* FUNCTIONS : InitializeApplication() - Sets up Class data structure *
* and registers window class. *
* *
* InitializeInstance () - Does a per-instance initial- *
* ization of MultiPad. Creates *
* the "frame" and MDI client. *
* *
***************************************************************************/
#include "multipad.h"
char szFrame[] = "mpframe"; /* Class name for "frame" window */
char szChild[] = "mpchild"; /* Class name for MDI window */
/****************************************************************************
* *
* FUNCTION : InitializeApplication () *
* *
* PURPOSE : Sets up the class data structures and does a one-time *
* initialization of the app by registering the window classes*
* *
* RETURNS : TRUE - If RegisterClass() was successful for both classes.*
* FALSE - otherwise. *
* *
****************************************************************************
BOOL FAR PASCAL InitializeApplication()
{
WNDCLASS wc;
/* Register the frame class */
wc.style = 0;
wc.lpfnWndProc = MPFrameWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInst;
wc.hIcon = LoadIcon(hInst,IDMULTIPAD);
wc.hCursor = LoadCursor(NULL,IDC_ARROW);
wc.hbrBackground = COLOR_APPWORKSPACE+1;
wc.lpszMenuName = IDMULTIPAD;
wc.lpszClassName = szFrame;
if (!RegisterClass (&wc) )
return FALSE;
/* Register the MDI child class */
wc.lpfnWndProc = MPMDIChildWndProc;
wc.hIcon = LoadIcon(hInst,IDNOTE);
wc.lpszMenuName = NULL;
wc.cbWndExtra = CBWNDEXTRA;
wc.lpszClassName = szChild;
if (!RegisterClass(&wc))
return FALSE;
return TRUE;
}
/****************************************************************************
* *
* FUNCTION : InitializeInstance () *
* *
* PURPOSE : Performs a per-instance initialization of MultiPad. It *
* also creates the frame and an MDI window. *
* *
* RETURNS : TRUE - If initialization was successful. *
* FALSE - otherwise. *
* *
****************************************************************************
BOOL FAR PASCAL InitializeInstance(LPSTR lpCmdLine, WORD nCmdShow)
{
extern HWND hwndMDIClient;
char sz[80], *pCmdLine;
HDC hdc;
HMENU hmenu;
/* Get the base window title */
LoadString (hInst, IDS_APPNAME, sz, sizeof(sz));
/* Create the frame */
hwndFrame = CreateWindow (szFrame,
sz,
WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
CW_USEDEFAULT,
0,
CW_USEDEFAULT,
0,
NULL,
NULL,
hInst,
NULL);
if ((!hwndFrame) || (!hwndMDIClient))
return FALSE;
/* Load main menu accelerators */
if (!(hAccel = LoadAccelerators (hInst, IDMULTIPAD)))
return FALSE;
/* Display the frame window */
ShowWindow (hwndFrame, nCmdShow);
UpdateWindow (hwndFrame);
/* If the command line string is empty, nullify the pointer to it
** else copy command line into our data segment
*/
if ( lpCmdLine && !(*lpCmdLine))
pCmdLine = NULL;
else {
pCmdLine = (char *) LocalAlloc(LPTR, lstrlen(lpCmdLine) + 1);
if (pCmdLine)
lstrcpy(pCmdLine, lpCmdLine);
}
/* Add the first MDI window */
AddFile (pCmdLine);
/* if we allocated a buffer then free it */
if (pCmdLine)
LocalFree((LOCALHANDLE) pCmdLine);
/* Default to minimized windows after the first. */
styleDefault = 0L;
return TRUE;
}
MPOPEN.C
CD-ROM Disc Path: \SAMPCODE\WIN_SDK\MULTIPAD\MPOPEN.C
/***************************************************************************
* *
* MODULE : MpOpen.c *
* *
* PURPOSE : Contains the file open dialog function and it's helper *
* functions. *
* *
* FUNCTIONS : IsWild () - Ascertains that the input string *
* contains a DOS wildcard character. *
* *
* SelectFile() - If filename supplied contains a *
* wildcard, this function fills the *
* listboxes in File/Open dialog, else*
* the dialog is closed. *
* *
* FileOpenDlgProc() - Dialog funcion for the File/Open *
* dialog. *
* *
* GetFileName () - Gets a file name from the user. *
* *
***************************************************************************/
#include "multipad.h"
char szPropertyName [] = "FILENAME";/* Name of the File name property list it
int FAR PASCAL DialogBoxParam ( HANDLE, LPSTR, HWND, FARPROC, LONG);
/****************************************************************************
* *
* FUNCTION : IsWild ( psz ) *
* *
* PURPOSE : Checks if the string (referenced by a NEAR pointer) *
* contains a DOS wildcard character ("*" or "?"). *
* *
* RETURNS : TRUE - iff the string contains a wildcard character. *
* FALSE - otherwise. . *
* *
****************************************************************************
BOOL NEAR PASCAL IsWild( psz )
register PSTR psz;
{
for(;;)
switch (*psz++){
case '*':
case '?':
/* Found wildcard */
return TRUE;
case 0:
/* Reached end of string */
return FALSE;
default:
continue;
}
}
/****************************************************************************
* *
* FUNCTION : FileExists(pch) *
* *
* PURPOSE : Checks to see if a file exists with the path/filename *
* described by the string pointed to by 'pch'. *
* *
* RETURNS : TRUE - if the described file does exist. *
* FALSE - otherwise. *
* *
****************************************************************************
BOOL FileExists(PSTR pch)
{
int fh;
if ((fh = _lopen((LPSTR) pch, 0)) < 0)
return(FALSE);
_lclose(fh);
return(TRUE);
}
/****************************************************************************
* *
* FUNCTION : SelectFile ( hwnd ) *
* *
* PURPOSE : Reads the string in the edit control of the File/Open *
* dialog. If it contains a wildcard, then it attempts to *
* fill the listboxes in the File/Open dialog. Othewise it *
* ends the dialog. Modifies the FILENAME item in the property*
* list of the window. *
* *
****************************************************************************
VOID NEAR PASCAL SelectFile( hwnd )
register HWND hwnd;
{
register PSTR pch;
PSTR pch2;
int cch;
char szBuf[256];
/* Get handle (near address) to filename data in window's property list *
pch = (PSTR)GetProp (hwnd, PROP_FILENAME);
/* Get the text from the dialog's edit control into this address */
GetDlgItemText (hwnd, IDD_FILENAME, pch, 64);
if ( IsWild (pch)){
/* Select the directory and make a listing of the directories */
DlgDirList(hwnd, (LPSTR)pch, IDD_DIRS, IDD_PATH, ATTR_DIRS);
/* Obtain the filename-only part of the path in the edit control */
for (pch2 = pch; *pch; pch++)
if (*pch == '\\' || *pch == ':')
pch2 = pch + 1;
/* List the files in this directory based on the wildcard. */
DlgDirList(hwnd, (LPSTR)pch2, IDD_FILES, IDD_PATH, ATTR_FILES);
/* Set the dialog's edit control to the filename part of path
* string.
*/
SetDlgItemText (hwnd, IDD_FILENAME, pch2);
}
else
{
/* The filename in the property list is not a wildcard */
if (FileExists (pch)){
RemoveProp (hwnd, PROP_FILENAME);
EndDialog (hwnd, 0);
}
else{
MPError ( hwnd, MB_OK | MB_SYSTEMMODAL, IDS_CANTOPEN, (LPSTR) pch);
SetActiveWindow (hwnd);
}
}
}
/****************************************************************************
* *
* FUNCTION : FileOpenDlgProc() *
* *
* PURPOSE : Dialog function for the File/Open dialog. Takes care of *
* calling the appropriate functions for extracting the *
* filename and wildcard, filling the listboxes and changing *
* the FILENAME item in the property list for the window. *
* *
****************************************************************************
BOOL FAR PASCAL FileOpenDlgProc ( hwnd, message, wParam, lParam)
register HWND hwnd;
WORD message;
register WORD wParam;
LONG lParam;
{
PSTR pch;
switch (message){
case WM_INITDIALOG:
/* Set the default file extension on edit window, and try to
* get a listing of the files and directories.
*/
SetDlgItemText ( hwnd, IDD_FILENAME, DEFFILESEARCH);
SetProp (hwnd, PROP_FILENAME, LOWORD(lParam));
SendDlgItemMessage (hwnd, IDD_FILENAME, EM_LIMITTEXT, 64, 0L);
SelectFile (hwnd);
break;
case WM_COMMAND:
switch (wParam){
case IDOK:
SelectFile(hwnd);
break;
case IDCANCEL:
/* Set the filename in the prop. list to NULL and quit */
pch = (PSTR) GetProp (hwnd, PROP_FILENAME);
*pch = 0;
EndDialog (hwnd, 0);
break;
case IDD_FILENAME:
/* Enable the OK button if the edit control has text. */
EnableWindow ( GetDlgItem (hwnd, IDOK),
GetWindowTextLength ((HWND)LOWORD (lParam)));
break;
case IDD_FILES:
/* The files listbox. If file selection has changed, fill
* the new filename into the property list buffer and set
* text in edit control.
*/
if (HIWORD(lParam) == LBN_SELCHANGE){
pch = (PSTR) GetProp (hwnd, PROP_FILENAME);
DlgDirSelect (hwnd, (LPSTR)pch, IDD_FILES);
SetDlgItemText (hwnd, IDD_FILENAME, (LPSTR)pch);
}
else if (HIWORD(lParam) == LBN_DBLCLK)
/* if the item was double-clicked, try to open it */
SelectFile(hwnd);
break;
case IDD_DIRS:
/* The directories listbox. Append current filename in edit
* control (stripped of the path prefix) to the name from
* the property list and set the new string in the edit
* control.
*/
if (HIWORD(lParam) == LBN_SELCHANGE){
PSTR pch2, pchT, pchS;
pch = (PSTR) GetProp (hwnd, PROP_FILENAME);
/* Get the new drive/dir */
DlgDirSelect (hwnd, pch, IDD_DIRS);
pch2 = pch + lstrlen(pch);
/* Fetch current contents of dialog's edit control and append
* it to name from property list... */
GetDlgItemText(hwnd,IDD_FILENAME,(LPSTR)pch2,64);
if (*pch2 == 0){
SetDlgItemText(hwnd, IDD_FILENAME, DEFFILESEARCH);
GetDlgItemText(hwnd,IDD_FILENAME,(LPSTR)pch2,64);
}
else {
pchS = pch;
for (pchT = pch = pch2; *pch; pch++) {
if (*pch == '\\' || *pch == ':')
pchT = pch2;
else
*pchT++ = *pch;
}
*pchT = 0;
pch = pchS;
}
/* Set the edit control with new string */
SetDlgItemText (hwnd, IDD_FILENAME, (LPSTR)pch);
}
else if (HIWORD(lParam) == LBN_DBLCLK)
SelectFile (hwnd);
break;
default:
return FALSE;
}
break;
default:
return FALSE;
}
return TRUE;
}
/****************************************************************************
* *
* FUNCTION : GetFilename ( pstr ) *
* *
* PURPOSE : Gets a filename from the user by calling the File/Open *
* dialog. *
* *
****************************************************************************
VOID NEAR PASCAL GetFileName(PSTR pstr)
{
FARPROC lpfn;
lpfn = MakeProcInstance (FileOpenDlgProc, hInst);
DialogBoxParam (hInst, IDD_FILEOPEN, hwndFrame, lpfn, MAKELONG(pstr,0));
FreeProcInstance (lpfn);
}
MPPRINT.C
CD-ROM Disc Path: \SAMPCODE\WIN_SDK\MULTIPAD\MPPRINT.C
/***************************************************************************
* *
* MODULE : MpPrint() *
* *
* PURPOSE : Printing code for MultiPad. *
* *
* FUNCTIONS : GetPrinterDC () - Creates a printer DC for the *
* default device. *
* *
* AbortProc () - Export proc. for GDI to check*
* print abort. *
* *
* PrintDlgProc () - Dialog function for the print*
* cancel dialog. *
* *
* PrintFile () - Prints the contents of the *
* edit control. *
* *
* GetInitializationData () - Gets DC initialisation data *
* from a DC supporting *
* ExtDeviceMode(). *
* *
***************************************************************************/
#include "multipad.h"
BOOL fAbort; /* TRUE if the user has aborted the print job */
HWND hwndPDlg; /* Handle to the cancel print dialog */
char szDevice[160]; /* Contains the device, the driver, and the port */
PSTR szDriver; /* Pointer to the driver name */
PSTR szPort; /* Port, ie, LPT1 */
PSTR szTitle; /* Global pointer to job title */
int iPrinter = 0; /* level of available printer support. */
/* 0 - no printer available */
/* 1 - printer available */
/* 2 - driver supports 3.0 device initialization */
HANDLE hInitData=NULL; /* handle to initialization data */
char szExtDeviceMode[] = "EXTDEVICEMODE";
/****************************************************************************
* *
* FUNCTION : GetPrinterDC () *
* *
* PURPOSE : Creates a printer display context for the default device. *
* As a side effect, it sets the szDevice and szPort variables*
* It also sets iPrinter to the supported level of printing. *
* *
* RETURNS : HDC - A handle to printer DC. *
* *
****************************************************************************
HDC FAR PASCAL GetPrinterDC(void)
{
char szT[32];
HDC hdc;
LPSTR lpdevmode = NULL;
iPrinter = 0;
/* Get the printer information from win.ini into a buffer and
* null terminate it.
*/
GetProfileString ( "windows", "device", "" ,szDevice, sizeof(szDevice));
for (szDriver = szDevice; *szDriver && *szDriver != ','; szDriver++)
;
if (*szDriver)
*szDriver++ = 0;
/* From the current position in the buffer, null teminate the
* list of ports
*/
for (szPort = szDriver; *szPort && *szPort != ','; szPort++)
;
if (*szPort)
*szPort++ = 0;
/* if the device, driver and port buffers all contain meaningful data,
* proceed.
*/
if (!*szDevice || !*szDriver || !*szPort){
*szDevice = 0;
return NULL;
}
/* Create the printer display context */
if (hInitData){
/* Get a pointer to the initialization data */
lpdevmode = (LPSTR) LocalLock (hInitData);
if (lstrcmp (szDevice, lpdevmode)){
/* User has changed the device... cancel this setup, as it is
* invalid (although if we worked harder we could retain some
* of it).
*/
lpdevmode = NULL;
LocalUnlock (hInitData);
LocalFree (hInitData);
hInitData = NULL;
}
}
hdc = CreateDC (szDriver, szDevice, szPort, lpdevmode);
/* Unlock initialization data */
if (hInitData)
LocalUnlock (hInitData);
if (!hdc)
return NULL;
iPrinter = 1;
/* Find out if ExtDeviceMode() is supported and set flag appropriately */
if (GetProcAddress (GetModuleHandle (szDriver), szExtDeviceMode))
iPrinter = 2;
return hdc;
}
/****************************************************************************
* *
* FUNCTION : AbortProc() *
* *
* PURPOSE : To be called by GDI print code to check for user abort. *
* *
****************************************************************************
int FAR PASCAL AbortProc ( hdc, reserved )
HDC hdc;
WORD reserved;
{
MSG msg;
/* Allow other apps to run, or get abort messages */
while (!fAbort && PeekMessage (&msg, NULL, NULL, NULL, TRUE))
if (!hwndPDlg || !IsDialogMessage (hwndPDlg, &msg)){
TranslateMessage (&msg);
DispatchMessage (&msg);
}
return !fAbort;
}
/****************************************************************************
* *
* FUNCTION : PrintDlgProc () *
* *
* PURPOSE : Dialog function for the print cancel dialog box. *
* *
* RETURNS : TRUE - OK to abort/ not OK to abort *
* FALSE - otherwise. *
* *
****************************************************************************
BOOL FAR PASCAL PrintDlgProc(HWND hwnd, WORD msg, WORD wParam, LONG lParam)
{
switch (msg){
case WM_INITDIALOG:
/* Set up information in dialog box */
SetDlgItemText (hwnd, IDD_PRINTDEVICE, (LPSTR)szDevice);
SetDlgItemText (hwnd, IDD_PRINTPORT, (LPSTR)szPort);
SetDlgItemText (hwnd, IDD_PRINTTITLE, (LPSTR)szTitle);
break;
case WM_COMMAND:
/* abort printing if the only button gets hit */
fAbort = TRUE;
break;
default:
return FALSE;
}
return TRUE;
}
/****************************************************************************
* *
* FUNCTION : PrintFile () *
* *
* PURPOSE : Prints the contents of the edit control. *
* *
****************************************************************************
VOID FAR PASCAL PrintFile(HWND hwnd)
{
HDC hdc;
int yExtPage;
char sz[32];
WORD cch;
WORD ich;
PSTR pch;
WORD iLine;
WORD nLinesEc;
WORD i;
HANDLE hT;
FARPROC lpfnAbort;
FARPROC lpfnPDlg;
HWND hwndPDlg;
WORD dy;
int yExtSoFar;
WORD fError = TRUE;
HWND hwndEdit;
hwndEdit = (HWND)GetWindowWord(hwnd,GWW_HWNDEDIT);
/* Create the job title by loading the title string from STRINGTABLE */
cch = LoadString (hInst, IDS_PRINTJOB, sz, sizeof(sz));
szTitle = sz + cch;
cch += GetWindowText (hwnd, sz + cch, 32 - cch);
sz[31] = 0;
/* Make instances of the Abort proc. and the Print dialog function */
lpfnAbort = MakeProcInstance (AbortProc, hInst);
if (!lpfnAbort)
goto getout;
lpfnPDlg = MakeProcInstance (PrintDlgProc, hInst);
if (!lpfnPDlg)
goto getout4;
/* Initialize the printer */
hdc = GetPrinterDC();
if (!hdc)
goto getout5;
/* Disable the main application window and create the Cancel dialog */
EnableWindow (hwndFrame, FALSE);
hwndPDlg = CreateDialog (hInst, IDD_PRINT, hwnd, lpfnPDlg);
if (!hwndPDlg)
goto getout3;
ShowWindow (hwndPDlg, SW_SHOW);
UpdateWindow (hwndPDlg);
/* Allow the app. to inform GDI of the escape function to call */
if (Escape (hdc, SETABORTPROC, 0, (LPSTR)lpfnAbort, NULL) < 0)
goto getout1;
/* Initialize the document */
if (Escape (hdc, STARTDOC, cch, (LPSTR)sz, NULL) < 0)
goto getout1;
/* Get the height of one line and the height of a page */
dy = HIWORD (GetTextExtent (hdc, "CC", 2));
yExtPage = GetDeviceCaps (hdc, VERTRES);
/* Get the lines in document and and a handle to the text buffer */
iLine = 0;
yExtSoFar = 0;
nLinesEc = (WORD)SendMessage (hwndEdit, EM_GETLINECOUNT, 0, 0L);
hT = (HANDLE)SendMessage (hwndEdit, EM_GETHANDLE, 0, 0L);
/* While more lines print out the text */
while (iLine < nLinesEc){
if (yExtSoFar + dy > yExtPage){
/* Reached the end of a page. Tell the device driver to eject a
* page
*/
if (Escape (hdc, NEWFRAME, 0, NULL, NULL) < 0 || fAbort)
goto getout2;
yExtSoFar = 0;
}
/* Get the length and position of the line in the buffer
* and lock from that offset into the buffer */
ich = (WORD)SendMessage (hwndEdit, EM_LINEINDEX, iLine, 0L);
cch = (WORD)SendMessage (hwndEdit, EM_LINELENGTH, ich, 0L);
pch = LocalLock(hT) + ich;
/* Print the line and unlock the text handle */
TextOut (hdc, 0, yExtSoFar, (LPSTR)pch, cch);
LocalUnlock (hT);
/* Test and see if the Abort flag has been set. If yes, exit. */
if (fAbort)
goto getout2;
/* Move down the page */
yExtSoFar += dy;
iLine++;
}
/* Eject the last page. */
if (Escape (hdc, NEWFRAME, 0, NULL, NULL) < 0)
goto getout2;
/* Complete the document. */
if (Escape (hdc, ENDDOC, 0, NULL, NULL) < 0){
getout2:
/* Ran into a problem before NEWFRAME? Abort the document */
Escape( hdc, ABORTDOC, 0, NULL, NULL);
}
else
fError=FALSE;
getout3:
/* Close the cancel dialog and re-enable main app. window */
EnableWindow (hwndFrame, TRUE);
DestroyWindow (hwndPDlg);
getout1:
DeleteDC(hdc);
getout5:
/* Get rid of dialog procedure instances */
FreeProcInstance (lpfnPDlg);
getout4:
FreeProcInstance (lpfnAbort);
getout:
/* Error? make sure the user knows... */
if (fError)
MPError (hwnd, MB_OK | MB_ICONEXCLAMATION, IDS_PRINTERROR, (LPSTR)szTitle);
return;
}
/****************************************************************************
* *
* FUNCTION : GetInitializationData() *
* *
* PURPOSE : Gets DC initialization data from a printer driver *
* supporting ExtDeviceMode(). Called in response to the *
* File/Printer setup menu selection. *
* *
* This function allows the user to change the printer *
* settings FOR MULTIPAD ONLY. This allows Multipad to print *
* in a variety of settings without messing up any other *
* applications. In a more sophisticated application, this *
* setup could even be saved on a document-by-document basis. *
* *
****************************************************************************
BOOL FAR PASCAL GetInitializationData( hwnd )
HWND hwnd ;
{
LPSTR lpOld;
LPSTR lpNew;
FARPROC lpfn;
HANDLE hT,hDrv;
char sz[32];
WORD cb;
int flag;
/* Pop up dialog for user and retain data in app buffer */
flag = DM_PROMPT | DM_COPY;
/* Load the device driver and find the ExtDeviceMode() function */
wsprintf (sz, "%s.drv", (LPSTR)szDriver);
if ((hDrv = LoadLibrary (sz)) < 32)
return FALSE;
if (!(lpfn = GetProcAddress (hDrv, szExtDeviceMode)))
return FALSE;
if (hInitData){
/* We have some old data... we want to modify the previously specified
* setup rather than starting with the default setup.
*/
lpOld = (LPSTR)LocalLock(hInitData);
flag |= DM_MODIFY;
}
else
lpOld = NULL;
/* Get the number of bytes needed for the init data */
cb = (*lpfn) (hwnd,
hDrv,
NULL,
(LPSTR)szDevice,
(LPSTR)szPort,
(LPDEVMODE)NULL,
(LPSTR)NULL,
0);
/* Grab some memory for the new data and lock it. */
hT = LocalAlloc (LHND,cb);
lpNew = (LPSTR)LocalLock (hT);
/* Post the device mode dialog. 0 flag iff user hits OK button */
if ((*lpfn) (hwnd,
hDrv,
(LPDEVMODE)lpNew,
(LPSTR)szDevice,
(LPSTR)szPort,
(LPDEVMODE)lpOld,
(LPSTR)NULL,
flag)==IDOK)
flag = 0;
/* Unlock the input structures */
LocalUnlock (hT);
if (hInitData)
LocalUnlock (hInitData);
/* If the user hit OK and everything worked, free the original init.
* data and retain the new one. Otherwise, toss the new buffer.
*/
if (flag)
LocalFree (hT);
else{
if (hInitData)
LocalFree (hInitData);
hInitData = hT;
}
FreeLibrary(hDrv);
return (!flag);
}
MULTIPAD.C
CD-ROM Disc Path: \SAMPCODE\WIN_SDK\MULTIPAD\MULTIPAD.C
/***************************************************************************
* *
* PROGRAM : MultiPad.c *
* *
* PURPOSE : To give a multi-Notepad demonstration of the new MDI *
* API in Windows 3.0 *
* *
* FUNCTIONS : WinMain() - Calls the initialization function *
* and processes message loop *
* *
* MPFrameWndProc() - Window function for the "frame" *
* window, which controls the menu *
* and contains the MDI document *
* windows as child windows. *
* *
* MPMDIChildWndProc() - Window function for the individual *
* document windows *
* *
* InitializeMenu() - Handles enabling/greying of menu *
* items according to the app's state.*
* *
* CloseAllChildren - Destroys all MDI child windows. *
* *
* CommandHandler() - Processes the "frame" window's *
* WM_COMMAND messages. *
* *
* AboutDlgProc() - Dialog function for the ubiquitous *
* About.. dialog. *
* *
* SetWrap() - Alters word wrapping in the edit *
* control. *
* *
* MPError() - Flashes an error messagebox. *
* *
* QueryCloseChild - Prompts for saving current MDI *
* child window. *
* *
* QueryCloseAllChildren() - Asks whether it is OK to close *
* down app. *
* *
***************************************************************************/
#include "multipad.h"
/* global variables used in this module or among more than one module */
HANDLE hInst; /* Program instance handle */
HANDLE hAccel; /* Main accelerator resource */
HWND hwndFrame = NULL; /* Handle to main window */
HWND hwndMDIClient = NULL; /* Handle to MDI client */
HWND hwndActive = NULL; /* Handle to currently activated child */
HWND hwndActiveEdit = NULL; /* Handle to edit control */
LONG styleDefault = WS_MAXIMIZE; /* Default style bits for child windows
/* The first window is created maximized */
/* to resemble Notepad. Later children */
/* are normal windows. */
LPSTR lpMenu = IDMULTIPAD; /* Contains the resource id of the */
/* current frame menu */
/* Forward declarations of helper functions in this module */
VOID NEAR PASCAL InitializeMenu (HANDLE);
VOID NEAR PASCAL CommandHandler (HWND,WORD);
VOID NEAR PASCAL SetWrap (HWND,BOOL);
BOOL NEAR PASCAL QueryCloseAllChildren ( VOID );
int NEAR PASCAL QueryCloseChild (HWND);
/****************************************************************************
* *
* FUNCTION : WinMain(HANDLE, HANDLE, LPSTR, int) *
* *
* PURPOSE : Creates the "frame" window, does some initialization and *
* enters the message loop. *
* *
****************************************************************************
int NEAR PASCAL WinMain(hInstance, hPrevInstance, lpszCmdLine, nCmdShow)
HANDLE hInstance;
HANDLE hPrevInstance;
LPSTR lpszCmdLine;
int nCmdShow;
{
MSG msg;
hInst = hInstance;
/* If this is the first instance of the app. register window classes */
if (!hPrevInstance){
if (!InitializeApplication ())
return 0;
}
/* Create the frame and do other initialization */
if (!InitializeInstance (lpszCmdLine, nCmdShow))
return 0;
/* Enter main message loop */
while (GetMessage (&msg, NULL, 0, 0)){
/* If a keyboard message is for the MDI , let the MDI client
* take care of it. Otherwise, check to see if it's a normal
* accelerator key (like F3 = find next). Otherwise, just handle
* the message as usual.
*/
if ( !TranslateMDISysAccel (hwndMDIClient, &msg) &&
!TranslateAccelerator (hwndFrame, hAccel, &msg)){
TranslateMessage (&msg);
DispatchMessage (&msg);
}
}
return 0;
}
/****************************************************************************
* *
* FUNCTION : MPFrameWndProc (hwnd, msg, wParam, lParam ) *
* *
* PURPOSE : The window function for the "frame" window, which controls *
* the menu and encompasses all the MDI child windows. Does *
* the major part of the message processing. Specifically, in *
* response to: *
* *
* WM_CREATE : Creates and displays the "frame". *
* *
* WM_INITMENU : Sets up the state of the menu. *
* *
* WM_WININICHANGE & : If default printer characteristics*
* WM_DEVMODECHANGE have been changed, reinitialises *
* printer DC. *
* *
* WM_COMMAND : Passes control to a command- *
* handling function. *
* *
* WM_CLOSE : Quits the app. if all the child *
* windows agree. *
* *
* WM_QUERYENDSESSION : Checks that all child windows *
* agree to quit. *
* *
* WM_DESTROY : Destroys frame window and quits *
* app. *
* *
****************************************************************************
LONG FAR PASCAL MPFrameWndProc ( hwnd, msg, wParam, lParam )
register HWND hwnd;
WORD msg;
register WORD wParam;
LONG lParam;
{
switch (msg){
case WM_CREATE:{
CLIENTCREATESTRUCT ccs;
HDC hdc;
/* Find window menu where children will be listed */
ccs.hWindowMenu = GetSubMenu (GetMenu(hwnd),WINDOWMENU);
ccs.idFirstChild = IDM_WINDOWCHILD;
/* Create the MDI client filling the client area */
hwndMDIClient = CreateWindow ("mdiclient",
NULL,
WS_CHILD | WS_CLIPCHILDREN |
WS_VSCROLL | WS_HSCROLL,
0,
0,
0,
0,
hwnd,
0xCAC,
hInst,
(LPSTR)&ccs);
ShowWindow (hwndMDIClient,SW_SHOW);
/* Check if printer can be initialized */
if (hdc = GetPrinterDC ()){
DeleteDC (hdc);
}
break;
}
case WM_INITMENU:
/* Set up the menu state */
InitializeMenu ((HMENU)wParam);
break;
case WM_WININICHANGE:
case WM_DEVMODECHANGE:{
/* If control panel changes default printer characteristics,
* reinitialize our printer information...
*/
HDC hdc;
if (hdc = GetPrinterDC ()){
DeleteDC (hdc);
}
break;
}
case WM_COMMAND:
/* Direct all menu selection or accelerator commands to another
* function
*/
CommandHandler (hwnd,wParam);
break;
case WM_CLOSE:
/* don't close if any children cancel the operation */
if (!QueryCloseAllChildren ())
break;
DestroyWindow (hwnd);
break;
case WM_QUERYENDSESSION:
/* Before session ends, check that all files are saved */
return QueryCloseAllChildren ();
case WM_DESTROY:
PostQuitMessage (0);
break;
default:
/* use DefFrameProc() instead of DefWindowProc() since there
* are things that have to be handled differently because of MDI
*/
return DefFrameProc (hwnd,hwndMDIClient,msg,wParam,lParam);
}
return 0;
}
/****************************************************************************
* *
* FUNCTION : MPMDIWndProc ( hwnd, msg, wParam, lParam ) *
* *
* PURPOSE : The window function for the individual document windows, *
* each of which has a "note". Each of these windows contain *
* one multi-line edit control filling their client area. *
* In response to the following: *
* *
* WM_CREATE : Creates & diplays an edit control *
* and does some initialization. *
* *
* WM_MDIACTIVATE : Activates/deactivates the child. *
* *
* WM_SETFOCUS : Sets focus on the edit control. *
* *
* WM_SIZE : Resizes the edit control. *
* *
* WM_COMMAND : Processes some of the edit *
* commands, saves files and alters *
* the edit wrap state. *
* *
* WM_CLOSE : Closes child if it is ok to do so.*
* *
* WM_QUERYENDSESSION : Same as above. *
* *
****************************************************************************
LONG FAR PASCAL MPMDIChildWndProc ( hwnd, msg, wParam, lParam )
register HWND hwnd;
WORD msg;
register WORD wParam;
LONG lParam;
{
HWND hwndEdit;
switch (msg){
case WM_CREATE:
/* Create an edit control */
hwndEdit = CreateWindow ("edit",
NULL,
WS_CHILD|WS_HSCROLL|WS_MAXIMIZE|WS_VISIBLE|WS_VSCROLL|ES_AUTOHSC
0,
0,
0,
0,
hwnd,
ID_EDIT,
hInst,
NULL);
/* Remember the window handle and initialize some window attributes */
SetWindowWord (hwnd, GWW_HWNDEDIT, (WORD)hwndEdit);
SetWindowWord (hwnd, GWW_CHANGED, FALSE);
SetWindowWord (hwnd, GWW_WORDWRAP, FALSE);
SetWindowWord (hwnd, GWW_UNTITLED, TRUE);
SetFocus (hwndEdit);
break;
case WM_MDIACTIVATE:
/* If we're activating this child, remember it */
if (wParam){
hwndActive = hwnd;
hwndActiveEdit = (HWND)GetWindowWord (hwnd, GWW_HWNDEDIT);
}
else{
hwndActive = NULL;
hwndActiveEdit = NULL;
}
break;
case WM_QUERYENDSESSION:
/* Prompt to save the child */
return !QueryCloseChild (hwnd);
case WM_CLOSE:
/* If its OK to close the child, do so, else ignore */
if (QueryCloseChild (hwnd))
goto CallDCP;
else
break;
case WM_SIZE:{
RECT rc;
/* On creation or resize, size the edit control. */
hwndEdit = GetWindowWord (hwnd, GWW_HWNDEDIT);
GetClientRect (hwnd, &rc);
MoveWindow (hwndEdit,
rc.left,
rc.top,
rc.right-rc.left,
rc.bottom-rc.top,
TRUE);
goto CallDCP;
}
case WM_SETFOCUS:
SetFocus (GetWindowWord (hwnd, GWW_HWNDEDIT));
break;
case WM_COMMAND:
switch (wParam){
case ID_EDIT:
switch (HIWORD(lParam)){
case EN_CHANGE:
/* If the contents of the edit control have changed,
set the changed flag
*/
SetWindowWord (hwnd, GWW_CHANGED, TRUE);
break;
case EN_ERRSPACE:
/* If the control is out of space, honk */
MessageBeep (0);
break;
default:
goto CallDCP;
}
break;
case IDM_FILESAVE:
/* If empty file, ignore save */
if ((GetWindowWord(hwnd, GWW_UNTITLED)) && (!ChangeFile(hwnd)))
break;
/* Save the contents of the edit control and reset the
* changed flag
*/
SaveFile (hwnd);
SetWindowWord (hwnd, GWW_CHANGED, FALSE);
break;
case IDM_EDITWRAP: {
int fWrap = GetWindowWord (hwnd, GWW_WORDWRAP);
/* Set the wrap state, or report it */
if (LOWORD (lParam)){
fWrap = !fWrap;
SetWrap (hwnd, fWrap);
}
/* return wrap state */
return fWrap;
}
default:
goto CallDCP;
}
break;
default:
CallDCP:
/* Again, since the MDI default behaviour is a little different,
* call DefMDIChildProc instead of DefWindowProc()
*/
return DefMDIChildProc (hwnd, msg, wParam, lParam);
}
return FALSE;
}
/****************************************************************************
* *
* FUNCTION : AboutDlgProc ( hwnd, msg, wParam, lParam ) *
* *
* PURPOSE : Dialog function for the About MultiPad... dialog. *
* *
****************************************************************************
BOOL FAR PASCAL AboutDlgProc ( hwnd, msg, wParam, lParam )
HWND hwnd;
register WORD msg;
register WORD wParam;
LONG lParam;
{
switch (msg){
case WM_INITDIALOG:
/* nothing to initialize */
break;
case WM_COMMAND:
switch (wParam){
case IDOK:
case IDCANCEL:
EndDialog(hwnd, 0);
break;
default:
return FALSE;
}
break;
default:
return FALSE;
}
return TRUE;
}
/****************************************************************************
* *
* FUNCTION : Initializemenu ( hMenu ) *
* *
* PURPOSE : Sets up greying, enabling and checking of main menu items *
* based on the app's state. *
* *
****************************************************************************
VOID NEAR PASCAL InitializeMenu ( hmenu )
register HANDLE hmenu;
{
register WORD status;
int i;
int j;
long l;
/* Is there any active child to talk to? */
if (hwndActiveEdit){
/* If edit control can respond to an undo request, enable the
* undo selection.
*/
if (SendMessage (hwndActiveEdit, EM_CANUNDO, 0, 0L))
status = MF_ENABLED;
else
status = MF_GRAYED;
EnableMenuItem (hmenu, IDM_EDITUNDO, status);
/* If edit control is non-empty, allow cut/copy/clear */
l = SendMessage (hwndActiveEdit, EM_GETSEL, 0, 0L);
status = (HIWORD(l) == LOWORD(l)) ? MF_GRAYED : MF_ENABLED;
EnableMenuItem (hmenu, IDM_EDITCUT, status);
EnableMenuItem (hmenu, IDM_EDITCOPY, status);
EnableMenuItem (hmenu, IDM_EDITCLEAR, status);
status=MF_GRAYED;
/* If the clipboard contains some CF_TEXT data, allow paste */
if (OpenClipboard (hwndFrame)){
int wFmt = 0;
while (wFmt = EnumClipboardFormats (wFmt))
if (wFmt == CF_TEXT){
status = MF_ENABLED;
break;
}
CloseClipboard ();
}
EnableMenuItem (hmenu, IDM_EDITPASTE, status);
/* Set the word wrap state for the window */
if ((WORD) SendMessage (hwndActive, WM_COMMAND, IDM_EDITWRAP, 0L))
status = MF_CHECKED;
else
status = MF_UNCHECKED;
CheckMenuItem (hmenu, IDM_EDITWRAP, status);
/* Enable search menu items only if there is a search string */
if (*szSearch)
status = MF_ENABLED;
else
status = MF_GRAYED;
EnableMenuItem (hmenu, IDM_SEARCHNEXT, status);
EnableMenuItem (hmenu, IDM_SEARCHPREV, status);
/* Enable File/Print only if a printer is available */
status = iPrinter ? MF_ENABLED : MF_GRAYED;
EnableMenuItem (hmenu, IDM_FILEPRINT, status);
/* select all and wrap toggle always enabled */
status = MF_ENABLED;
EnableMenuItem(hmenu, IDM_EDITSELECT, status);
EnableMenuItem(hmenu, IDM_EDITWRAP, status);
EnableMenuItem(hmenu, IDM_SEARCHFIND, status);
}
else {
/* There are no active child windows */
status = MF_GRAYED;
/* No active window, so disable everything */
for (i = IDM_EDITFIRST; i <= IDM_EDITLAST; i++)
EnableMenuItem (hmenu, i, status);
CheckMenuItem (hmenu, IDM_EDITWRAP, MF_UNCHECKED);
for (i = IDM_SEARCHFIRST; i <= IDM_SEARCHLAST; i++)
EnableMenuItem (hmenu, i, status);
EnableMenuItem (hmenu, IDM_FILEPRINT, status);
}
/* The following menu items are enabled if there is an active window */
EnableMenuItem (hmenu, IDM_FILESAVE, status);
EnableMenuItem (hmenu, IDM_FILESAVEAS, status);
EnableMenuItem (hmenu, IDM_WINDOWTILE, status);
EnableMenuItem (hmenu, IDM_WINDOWCASCADE, status);
EnableMenuItem (hmenu, IDM_WINDOWICONS, status);
EnableMenuItem (hmenu, IDM_WINDOWCLOSEALL, status);
/* Allow printer setup only if printer driver supports device initializat
if (iPrinter < 2)
status = MF_GRAYED;
EnableMenuItem ( hmenu, IDM_FILESETUP, status);
}
/****************************************************************************
* *
* FUNCTION : CloseAllChildren () *
* *
* PURPOSE : Destroys all MDI child windows. *
* *
****************************************************************************
VOID NEAR PASCAL CloseAllChildren ()
{
register HWND hwndT;
/* hide the MDI client window to avoid multiple repaints */
ShowWindow(hwndMDIClient,SW_HIDE);
/* As long as the MDI client has a child, destroy it */
while ( hwndT = GetWindow (hwndMDIClient, GW_CHILD)){
/* Skip the icon title windows */
while (hwndT && GetWindow (hwndT, GW_OWNER))
hwndT = GetWindow (hwndT, GW_HWNDNEXT);
if (!hwndT)
break;
SendMessage (hwndMDIClient, WM_MDIDESTROY, (WORD)hwndT, 0L);
}
}
/****************************************************************************
* *
* FUNCTION : CommandHandler () *
* *
* PURPOSE : Processes all "frame" WM_COMMAND messages. *
* *
****************************************************************************
VOID NEAR PASCAL CommandHandler ( hwnd, wParam )
register HWND hwnd;
register WORD wParam;
{
switch (wParam){
case IDM_FILENEW:
/* Add a new, empty MDI child */
AddFile (NULL);
break;
case IDM_FILEOPEN:
ReadFile (hwnd);
break;
case IDM_FILESAVE:
/* Save the active child MDI */
SendMessage (hwndActive, WM_COMMAND, IDM_FILESAVE, 0L);
break;
case IDM_FILESAVEAS:
/* Save active child MDI under another name */
if (ChangeFile (hwndActive))
SendMessage (hwndActive, WM_COMMAND, IDM_FILESAVE, 0L);
break;
case IDM_FILEPRINT:
/* Print the active child MDI */
PrintFile (hwndActive);
break;
case IDM_FILESETUP:
/* Set up the printer environment for this app */
GetInitializationData (hwnd);
break;
case IDM_FILEMENU:{
/* lengthen / shorten the size of the MDI menu */
HMENU hMenu;
HMENU hWindowMenu;
int i;
if (lpMenu == IDMULTIPAD){
lpMenu = IDMULTIPAD2;
i = SHORTMENU;
}
else{
lpMenu = IDMULTIPAD;
i = WINDOWMENU;
}
hMenu = LoadMenu (hInst, lpMenu);
hWindowMenu = GetSubMenu (hMenu, i);
/* Set the new menu */
hMenu = (HMENU)SendMessage (hwndMDIClient,
WM_MDISETMENU,
0,
MAKELONG(hMenu,hWindowMenu));
DestroyMenu (hMenu);
DrawMenuBar (hwndFrame);
break;
}
case IDM_FILEEXIT:
/* Close Multipad */
SendMessage (hwnd, WM_CLOSE, 0, 0L);
break;
case IDM_HELPABOUT:{
/* Bring up the ubiquitous Ego box */
FARPROC lpfn;
lpfn = MakeProcInstance(AboutDlgProc, hInst);
DialogBox (hInst, IDD_ABOUT, hwnd, lpfn);
FreeProcInstance (lpfn);
break;
}
/* The following are edit commands. Pass these off to the active
* child's edit control window.
*/
case IDM_EDITCOPY:
SendMessage (hwndActiveEdit, WM_COPY, 0, 0L);
break;
case IDM_EDITPASTE:
SendMessage (hwndActiveEdit, WM_PASTE, 0, 0L);
break;
case IDM_EDITCUT:
SendMessage (hwndActiveEdit, WM_CUT, 0, 0L);
break;
case IDM_EDITCLEAR:
SendMessage (hwndActiveEdit, EM_REPLACESEL, 0,( LONG)(LPSTR)"");
break;
case IDM_EDITSELECT:
SendMessage (hwndActiveEdit, EM_SETSEL, 0, MAKELONG(0, 0xe000));
break;
case IDM_EDITUNDO:
SendMessage (hwndActiveEdit, EM_UNDO, 0, 0L);
break;
case IDM_EDITWRAP:
SendMessage (hwndActive, WM_COMMAND, IDM_EDITWRAP, 1L);
break;
case IDM_SEARCHFIND:
/* Put up the find dialog box */
Find ();
break;
case IDM_SEARCHNEXT:
/* Find next occurence */
FindNext ();
break;
case IDM_SEARCHPREV:
/* Find previous occurence */
FindPrev ();
break;
/* The following are window commands - these are handled by the
* MDI Client.
*/
case IDM_WINDOWTILE:
/* Tile MDI windows */
SendMessage (hwndMDIClient, WM_MDITILE, 0, 0L);
break;
case IDM_WINDOWCASCADE:
/* Cascade MDI windows */
SendMessage (hwndMDIClient, WM_MDICASCADE, 0, 0L);
break;
case IDM_WINDOWICONS:
/* Auto - arrange MDI icons */
SendMessage (hwndMDIClient, WM_MDIICONARRANGE, 0, 0L);
break;
case IDM_WINDOWCLOSEALL:
/* Abort operation if something is not saved */
if (!QueryCloseAllChildren())
break;
CloseAllChildren();
/* Show the window since CloseAllChilren() hides the window
* for fewer repaints.
*/
ShowWindow( hwndMDIClient, SW_SHOW);
break;
default:
/*
* This is essential, since there are frame WM_COMMANDS generated
* by the MDI system for activating child windows via the
* window menu.
*/
DefFrameProc(hwnd, hwndMDIClient, WM_COMMAND, wParam, 0L);
}
}
/****************************************************************************
* *
* FUNCTION : SetWrap () *
* *
* PURPOSE : Changes the word wrapping in an edit control. Since this *
* cannot be done by direct means, the function creates a new *
* edit control, moves data from the old control to the new *
* control and destroys the original control. Note that the *
* function assumes that the child being modified is currently*
* active. * *
* *
****************************************************************************
VOID NEAR PASCAL SetWrap(hwnd, fWrap)
HWND hwnd;
BOOL fWrap;
{
LONG dws;
HANDLE hT;
HANDLE hTT;
HWND hwndOld;
HWND hwndNew;
RECT rc;
/* Change word wrap mode */
SetWindowWord (hwnd, GWW_WORDWRAP, fWrap);
/* Create the appropriate window style, adding a horizontal scroll
* facility if wrapping is not present.
*/
dws = WS_CHILD | WS_VSCROLL | ES_AUTOVSCROLL | ES_MULTILINE;
if (!fWrap)
dws |= WS_HSCROLL | ES_AUTOHSCROLL;
/* Create a new child window */
hwndNew = CreateWindow ( "edit",
NULL,
dws,
0,
SW_SHOW,
0,
0,
hwnd,
ID_EDIT,
hInst,
NULL);
/* Get handle to current edit control */
hwndOld = GetWindowWord (hwnd, GWW_HWNDEDIT);
/* Get the data handle of the old control */
hT = (HANDLE)SendMessage (hwndOld, EM_GETHANDLE, 0, 0L);
/* Create a dummy data handle and make it the handle to
* the old edit control( hT still references the text of
* old control).
*/
hTT = LocalAlloc (LHND, 0);
SendMessage (hwndOld, EM_SETHANDLE, hTT, 0L);
/* Make the new window the window of interest and destroy the
* old control.
*/
SetWindowWord (hwnd, GWW_HWNDEDIT, hwndNew);
hwndActiveEdit = hwndNew;
DestroyWindow (hwndOld);
/* Cause the window to be properly sized */
SendMessage (hwnd, WM_SIZE, 0, 0L);
/* Free the new window's old data handle and set it to
* hT (text of old edit control)
*/
LocalFree ((HANDLE)SendMessage (hwndNew, EM_GETHANDLE, 0, 0L));
SendMessage (hwndNew, EM_SETHANDLE, hT, 0L);
ShowWindow (hwndNew, SW_SHOW);
/* Set focus to the new edit control */
SetFocus (hwndNew);
}
/****************************************************************************
* *
* FUNCTION : MPError ( hwnd, flags, id, ...) *
* *
* PURPOSE : Flashes a Message Box to the user. The format string is *
* taken from the STRINGTABLE. *
* *
* RETURNS : Returns value returned by MessageBox() to the caller. *
* *
****************************************************************************
short FAR CDECL MPError(hwnd, bFlags, id, ...)
HWND hwnd;
WORD bFlags;
WORD id;
{
char sz[160];
char szFmt[128];
LoadString (hInst, id, szFmt, sizeof (szFmt));
wvsprintf (sz, szFmt, (LPSTR)(&id + 1));
LoadString (hInst, IDS_APPNAME, szFmt, sizeof (szFmt));
return MessageBox (hwndFrame, sz, szFmt, bFlags);
}
/****************************************************************************
* *
* FUNCTION : QueryCloseAllChildren() *
* *
* PURPOSE : Asks the child windows if it is ok to close up app. Nothing*
* is destroyed at this point. The z-order is not changed. *
* *
* RETURNS : TRUE - If all children agree to the query. *
* FALSE- If any one of them disagrees. *
* *
****************************************************************************
BOOL NEAR PASCAL QueryCloseAllChildren()
{
register HWND hwndT;
for ( hwndT = GetWindow (hwndMDIClient, GW_CHILD);
hwndT;
hwndT = GetWindow (hwndT, GW_HWNDNEXT) ){
/* Skip if an icon title window */
if (GetWindow (hwndT, GW_OWNER))
continue;
if (SendMessage (hwndT, WM_QUERYENDSESSION, 0, 0L))
return FALSE;
}
return TRUE;
}
/****************************************************************************
* *
* FUNCTION : QueryCloseChild (hwnd) *
* *
* PURPOSE : If the child MDI is unsaved, allow the user to save, not *
* save, or cancel the close operation. *
* *
* RETURNS : TRUE - if user chooses save or not save, or if the file *
* has not changed. *
* FALSE - otherwise. *
* *
****************************************************************************
BOOL NEAR PASCAL QueryCloseChild(hwnd)
register HWND hwnd;
{
char sz [64];
register int i;
/* Return OK if edit control has not changed. */
if (!GetWindowWord (hwnd, GWW_CHANGED))
return TRUE;
GetWindowText (hwnd, sz, sizeof(sz));
/* Ask user whether to save / not save / cancel */
i = MPError (hwnd,
MB_YESNOCANCEL|MB_ICONQUESTION,IDS_CLOSESAVE,
(LPSTR)sz);
switch (i){
case IDYES:
/* User wants file saved */
SaveFile(hwnd);
break;
case IDNO:
/* User doesn't want file saved */
break;
default:
/* We couldn't do the messagebox, or not ok to close */
return FALSE;
}
return TRUE;
}
MYPAL.C
CD-ROM Disc Path: \SAMPCODE\WIN_SDK\MYPAL\MYPAL.C
/***************************************************************************
* *
* PROGRAM : MyPal.c *
* *
* PURPOSE : Sets up a bar representation of the current physical *
* palette and displays useful information regarding *
* pixel colors and palette indices. *
* *
* FUNCTIONS : WinMain() - calls initialization function, *
* processes message loop *
* *
* WndProc() - Window function for app. Processes *
* window messages. *
* *
* ShowColor() - Displays a little box on each side of the *
* caption bar displaying the pixel color at the*
* mouse position. *
***************************************************************************/
#include <windows.h>
#include "mypal.h"
HANDLE hPal; /* Handle to the application's logical palette */
static WORD nSizeX; /* Width of the application window */
static WORD nSizeY; /* Height of the application window */
NPLOGPALETTE pLogPal; /* Pointer to program's logical palette *
WORD nXBorder; /* Width of window border */
WORD nXTitle; /* Width of title bar */
WORD nYTitle; /* Height of title bar */
BOOL bCaptureOn; /* Indicates if mouse capture is on */
int iIndex; /* Last index selected in palette */
char szTitlebuf[90];/* Buffer for pixel and palette info. text */
HDC hDCGlobal; /* The Screen DC */
int iNumColors; /* Number of colors supported by device */
int iRasterCaps; /* Raster capabilities */
int iPalSize; /* Size of Physical palette */
RECT rClientRect; /* Client rectangle coordinates */
DWORD dwPal[PALETTESIZE]; /* Stores palette entries for later lookup
int iGlobalXOffset;
int iGlobalYOffset;
int iYMiddle;
long FAR PASCAL WndProc (HWND, unsigned, WORD, LONG) ;
/****************************************************************************
* *
* FUNCTION : void ShowColor(HWND hWnd, HDC hDC) *
* *
* PURPOSE : Displays a little box on each side of the caption bar *
* displaying the pixel color at the mouse position. *
* *
****************************************************************************
void ShowColor (hWnd, hDC)
HWND hWnd;
HDC hDC;
{
HBRUSH hBrush, hOldBrush;
hBrush = CreateSolidBrush ( PALETTEINDEX(iIndex) );
hOldBrush = SelectObject (hDC,hBrush) ;
GetWindowRect (hWnd, (LPRECT)&rClientRect);
PatBlt ( hDC,
rClientRect.left + nXTitle + nXBorder + 1,
rClientRect.top + nXBorder,
nXTitle,
nYTitle,
PATCOPY);
PatBlt(hDC,
rClientRect.right - ( 3 * nXTitle + nXBorder + 2),
rClientRect.top + nXBorder,
nXTitle,
nYTitle,
PATCOPY);
SelectObject (hDC, hOldBrush);
DeleteObject (hBrush) ;
}
/****************************************************************************
* *
* FUNCTION : WinMain(HANDLE, HANDLE, LPSTR, int) *
* *
* PURPOSE : Creates the app. window and processes the message loop. *
* *
****************************************************************************
int PASCAL WinMain (hInstance, hPrevInstance, lpszCmdLine, nCmdShow)
HANDLE hInstance;
HANDLE hPrevInstance;
LPSTR lpszCmdLine;
int nCmdShow;
{
static char szAppName [] = "MyPal";
HWND hWnd;
WNDCLASS wndclass;
MSG msg ;
short int xScreen;
short int yScreen;
if (!hPrevInstance){
wndclass.style = CS_HREDRAW | CS_VREDRAW;
wndclass.lpfnWndProc = WndProc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = hInstance;
wndclass.hIcon = LoadIcon(hInstance, szAppName);
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW);
wndclass.hbrBackground = GetStockObject (BLACK_BRUSH);
wndclass.lpszMenuName = szAppName;
wndclass.lpszClassName = szAppName;
if (!RegisterClass (&wndclass))
return FALSE ;
}
/* Do some global initializations */
xScreen = GetSystemMetrics (SM_CXSCREEN);
yScreen = GetSystemMetrics (SM_CYSCREEN);
nXBorder = GetSystemMetrics (SM_CXFRAME);
nXTitle = GetSystemMetrics (SM_CXSIZE);
nYTitle = GetSystemMetrics (SM_CYSIZE);
iIndex = 0;
bCaptureOn = FALSE;
hDCGlobal = GetDC (NULL);
iPalSize = GetDeviceCaps (hDCGlobal, SIZEPALETTE);
iRasterCaps = GetDeviceCaps (hDCGlobal, RASTERCAPS);
iRasterCaps = (iRasterCaps & RC_PALETTE) ? TRUE : FALSE;
ReleaseDC (NULL,hDCGlobal);
if (iRasterCaps)
iNumColors = GetDeviceCaps(hDCGlobal, SIZEPALETTE);
else
iNumColors = GetDeviceCaps( hDCGlobal, NUMCOLORS);
nSizeX = ((xScreen - 2*nXBorder) / PALETTESIZE) * PALETTESIZE;
/* create the app. window */
hWnd = CreateWindow (szAppName,
"My Physical Palette ",
WS_OVERLAPPEDWINDOW,
(xScreen-nSizeX) / 2 - nXBorder,
yScreen - ( 4 * GetSystemMetrics (SM_CYCAPTION)),
nSizeX + 2 * nXBorder,
4 * GetSystemMetrics (SM_CYCAPTION),
NULL,
NULL,
hInstance,
NULL);
ShowWindow (hWnd, nCmdShow);
UpdateWindow (hWnd);
while (GetMessage (&msg, NULL, 0, 0)){
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
return msg.wParam ;
}
/****************************************************************************
* *
* FUNCTION: WndProc(HWND, unsigned, WORD, LONG) *
* *
* PURPOSE: Processes window messages and sets up a 256 bar representation
* of the current physical palette. Specifically, in response to: *
* *
* WM_CREATE -Allocates for and sets up a LOGPALETTE *
* structure, creates a logical palette the same *
* size as the physical palette and obtains a *
* handle to the logical palette. *
* *
* WM_DESTROY -Destroys the logical palette and shuts down app. *
* *
* WM_PAINT -Resizes client area to hold as many vertical *
* color bars as there are physical palette entries.*
* Also realises the current logical palette and *
* draws one color bar corresponding to each *
* palette entry *
* *
* WM_RBUTTONDOWN -Captures the mouse and initiates the below *
* process: *
* *
* WM_MOUSEMOVE -Following a WM_RBUTTONDOWN, if the right mouse *
* key is depressed, displays info about the *
* pixel RGB value and palette index of the mouse *
* coordinates. *
* *
* WM_RBUTTONUP -Release mouse capture and terminates the above *
* process *
* *
* WM_LBUTTONDOWN -Determines and displays the palette index and *
* RGB value of the bar under the mouse. *
* *
* WM_KEYDOWN -Allows use of the arrow keys in stepping thro' *
* palette entries. *
* *
****************************************************************************
long FAR PASCAL WndProc (hWnd, iMessage, wParam, lParam)
HWND hWnd;
unsigned iMessage;
WORD wParam;
LONG lParam;
{
HDC hDC;
PAINTSTRUCT ps;
WORD iLoop;
WORD nStart;
HMENU hMenu;
HBRUSH hBrush;
HBRUSH hOldBrush;
POINT pt;
static WORD nIncr;
static DWORD dwColor;
static DWORD dwLastColor;
static int i, x;
switch (iMessage){
case WM_DESTROY:
/* delete the handle to the logical palette if it has any
* color entries and quit.
*/
if (pLogPal->palNumEntries)
DeleteObject (hPal);
PostQuitMessage (0) ;
break ;
case WM_CREATE:
/* Allocate enough memory for a logical palette with
* PALETTESIZE entries and set the size and version fields
* of the logical palette structure.
*/
pLogPal = (NPLOGPALETTE) LocalAlloc (LMEM_FIXED,
(sizeof (LOGPALETTE) +
(sizeof (PALETTEENTRY) * (PALETTESIZE))));
pLogPal->palVersion = 0x300;
pLogPal->palNumEntries = PALETTESIZE;
/* fill in intensities for all palette entry colors */
for (iLoop = 0; iLoop < PALETTESIZE; iLoop++) {
*((WORD *) (&pLogPal->palPalEntry[iLoop].peRed)) = iLoop;
pLogPal->palPalEntry[iLoop].peBlue = 0;
pLogPal->palPalEntry[iLoop].peFlags = PC_EXPLICIT;
}
/* create a logical color palette according the information
* in the LOGPALETTE structure.
*/
hPal = CreatePalette ((LPLOGPALETTE) pLogPal) ;
break;
case WM_GETMINMAXINFO:
((LPRGPT)lParam)->iInfo[6] = nXBorder * 2 + PALETTESIZE;
((LPRGPT)lParam)->iInfo[7] = nXBorder * 2 + nYTitle*3;
return DefWindowProc (hWnd, iMessage, wParam, lParam) ;
break;
case WM_PAINT:
/* Divide client width into equal-sized parts, one per palette
* entry, and re-calculate client width so that it will display
* exactly as many vertical bars as there are palette entries.
*/
GetClientRect(hWnd,(LPRECT) &rClientRect);
nSizeX = (rClientRect.right - rClientRect.left);
nSizeX = (nSizeX/iNumColors) * iNumColors;
nSizeY = rClientRect.bottom - rClientRect.top;
GetWindowRect(hWnd,(LPRECT) &rClientRect);
/* Adjust window width so that it can display exactly
* as many vertical bars( of equal width) as there are palette
* colors.
*/
SetWindowPos( hWnd,
(HWND)NULL,
0,
0,
nSizeX + 2*nXBorder,
rClientRect.bottom - rClientRect.top,
SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
hDC = BeginPaint(hWnd, &ps);
/* Select the palette into the window device context and
* make the Palette Manager map the logical palette to the
* system palette (realize it).
*/
SelectPalette (hDC, hPal, 1);
RealizePalette (hDC);
/* Calculate width of each color bar to be displayed */
nIncr = nSizeX / iNumColors;
/* Paint the individual bars separately on the app. window */
for (nStart = iLoop = 0; iLoop < iNumColors; iLoop++){
/* Since this app. uses a logical palette, use the
* PALETTEINDEX macro to specify the palette entry
* index instead of using an explicit RGB value.
*/
hBrush = CreateSolidBrush (PALETTEINDEX (iLoop));
dwPal[iLoop] = GetNearestColor (hDC, PALETTEINDEX (iLoop) );
hOldBrush = SelectObject (hDC,hBrush) ;
PatBlt (hDC, nStart, 0, nIncr, nSizeY, PATCOPY);
nStart += nIncr;
SelectObject (hDC, hOldBrush);
DeleteObject (hBrush) ;
}
wsprintf (szTitlebuf, "MyPal Colors= %d", iNumColors);
SetWindowText (hWnd, (LPSTR)szTitlebuf);
EndPaint(hWnd,&ps);
break ;
case WM_MOUSEMOVE:
if (wParam & MK_RBUTTON) {
/* Convert mouse position to screen coordinates */
pt.x = LOWORD(lParam);
pt.y = HIWORD(lParam);
ClientToScreen(hWnd,&pt);
/* Get RGB value (color) of pixel under mouse coordinate */
dwColor = GetPixel(hDCGlobal, pt.x, pt.y);
/* If color value already exists in palette lookup table,
* obtain it's index.
*/
for (i=0 ; i < iNumColors ; i++)
if ( dwColor == dwPal[i] )
break;
iIndex = i;
/* If previous color value was not identical to current one,
* display color boxes on either side of title bar,
* the R, G, B values and palette index of current color.
*/
if (dwColor != dwLastColor) {
wsprintf ( szTitlebuf,
"MyPal Colors=%d Index=%d R=%3u G=%3u B=%3u",
iNumColors,
iIndex,
(WORD)(BYTE) GetRValue (dwColor),
(WORD)(BYTE) GetGValue (dwColor),
(WORD)(BYTE) GetBValue (dwColor));
SetWindowText (hWnd, (LPSTR)szTitlebuf);
ShowColor (hWnd, hDCGlobal);
dwLastColor = dwColor;
}
}
break;
case WM_RBUTTONDOWN:
/* Determine number of color bar under mouse, thus the index
* of color in palette.
*/
x = LOWORD(lParam);
iIndex = (x / nIncr );
wsprintf ( szTitlebuf,
"MyPal Colors=%d Index=%d PalSize=%d RasterCaps:%d",
iNumColors,
iIndex,
iPalSize,
iRasterCaps );
SetWindowText (hWnd, (LPSTR)szTitlebuf);
/* Set mouse capture so that subsequent WM_MOUSEMOVEs
* (with right mouse button depressed) will allow MyPal
* to display RGB info anywhere on the screen without losing
* the focus.
*/
SetCapture (hWnd);
bCaptureOn = TRUE;
hDCGlobal = GetDC(NULL);
if (hPal) {
SelectPalette (hDCGlobal, hPal, FALSE);
RealizePalette (hDCGlobal);
}
break;
case WM_RBUTTONUP:
/* Stops displaying RGB and palette info and releases mouse
* capture
*/
ReleaseDC (NULL, hDCGlobal);
bCaptureOn = FALSE;
ReleaseCapture ();
break;
case WM_MOVE:
/* If you have a wide column, this adds 1/2 so X is centered */
iGlobalXOffset = LOWORD (lParam);
iGlobalYOffset = HIWORD (lParam) + nXBorder;
break;
case WM_SIZE:
iYMiddle = (HIWORD (lParam)/2);
break;
case WM_LBUTTONDOWN:
case WM_KEYDOWN:
if (iMessage == WM_LBUTTONDOWN){
/* determine which column was hit by the mouse */
x = LOWORD(lParam);
iIndex = (x / nIncr );
}
else{
/* Use arrow keys to step thro' the palette entries */
switch (wParam) {
case VK_RIGHT:
case VK_UP:
/* go to next (higher) palette entry */
iIndex++;
break;
case VK_LEFT:
case VK_DOWN:
/* go to previous (lower) palette entry */
iIndex--;
break;
case VK_NEXT:
iIndex += 10;
break;
case VK_PRIOR:
iIndex -= 10;
break;
case VK_HOME:
/* go to first palette entry */
iIndex = 0;
break;
case VK_END:
/* go to last palette entry */
iIndex = iNumColors-1;
break;
default:
return 0L;
break;
}
/* Make sure the palette index is within range else
* set it to the limiting values and give a warning beep.
*/
if (iIndex < 0) {
iIndex = 0;
MessageBeep(1);
}
else{
if (iIndex > iNumColors-1) {
iIndex = iNumColors-1;
MessageBeep(1);
}
}
pt.x = (iIndex * nIncr) +
iGlobalXOffset +
((nIncr > 1) ? (nIncr / 2) : 1);
pt.y = iYMiddle + iGlobalYOffset;
SetCursorPos (pt.x, pt.y);
}
if (TRUE == bCaptureOn) {
MessageBeep(1);
break;
}
/* Select & realize the palette or the colors > 0x7
* will not match up.
*/
hDC = GetDC(NULL);
SelectPalette (hDC, hPal, 1);
RealizePalette (hDC) ;
dwColor = GetNearestColor (hDC, PALETTEINDEX (iIndex));
wsprintf ( szTitlebuf,
"MyPal Colors=%d Index=%d R=%3u G=%3u B=%3u",
iNumColors,
iIndex,
(WORD)(BYTE)GetRValue (dwColor),
(WORD)(BYTE)GetGValue (dwColor),
(WORD)(BYTE)GetBValue (dwColor)
);
SetWindowText (hWnd, (LPSTR)szTitlebuf);
ShowColor (hWnd,hDC);
ReleaseDC(NULL, hDC);
break;
default:
return DefWindowProc (hWnd, iMessage, wParam, lParam) ;
}
return 0L ;
}
OUTPUT.C
CD-ROM Disc Path: \SAMPCODE\WIN_SDK\OUTPUT\OUTPUT.C
/****************************************************************************
PROGRAM: Output.c
PURPOSE: Output template for Windows applications
FUNCTIONS:
WinMain() - calls initialization function, processes message loop
InitApplication() - initializes window data and registers window
InitInstance() - saves instance handle and creates main window
MainWndProc() - processes messages
About() - processes messages for "About" dialog box
****************************************************************************/
#include "windows.h"
#include "string.h"
#include "output.h"
HANDLE hInst;
HPEN hDashPen; /* "---" pen handle
HPEN hDotPen; /* "..." pen handle
HBRUSH hOldBrush; /* old brush handle
HBRUSH hRedBrush; /* red brush handle
HBRUSH hGreenBrush; /* green brush handle
HBRUSH hBlueBrush; /* blue brush handle
/****************************************************************************
FUNCTION: WinMain(HANDLE, HANDLE, LPSTR, int)
PURPOSE: calls initialization function, processes message loop
****************************************************************************/
int PASCAL WinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow)
HANDLE hInstance;
HANDLE hPrevInstance;
LPSTR lpCmdLine;
int nCmdShow;
{
MSG msg;
if (!hPrevInstance)
if (!InitApplication(hInstance))
return (FALSE);
if (!InitInstance(hInstance, nCmdShow))
return (FALSE);
while (GetMessage(&msg, NULL, NULL, NULL)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (msg.wParam);
}
/****************************************************************************
FUNCTION: InitApplication(HANDLE)
PURPOSE: Initializes window data and registers window class
****************************************************************************/
BOOL InitApplication(hInstance)
HANDLE hInstance;
{
WNDCLASS wc;
wc.style = NULL;
wc.lpfnWndProc = MainWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = "OutputMenu";
wc.lpszClassName = "OutputWClass";
return (RegisterClass(&wc));
}
/****************************************************************************
FUNCTION: InitInstance(HANDLE, int)
PURPOSE: Saves instance handle and creates main window
****************************************************************************/
BOOL InitInstance(hInstance, nCmdShow)
HANDLE hInstance;
int nCmdShow;
{
HWND hWnd;
hInst = hInstance;
hWnd = CreateWindow(
"OutputWClass",
"Output Sample Application",
WS_OVERLAPPEDWINDOW,
0,
0,
GetSystemMetrics(SM_CXSCREEN),
GetSystemMetrics(SM_CYSCREEN),
NULL,
NULL,
hInstance,
NULL
);
if (!hWnd)
return (FALSE);
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return (TRUE);
}
/****************************************************************************
FUNCTION: MainWndProc(HWND, unsigned, WORD, LONG)
PURPOSE: Processes messages
MESSAGES:
WM_COMMAND - application menu (About dialog box)
WM_CREATE - create window and objects
WM_PAINT - update window, draw objects
WM_DESTROY - destroy window
COMMENTS:
Handles to the objects you will use are obtained when the WM_CREATE
message is received, and deleted when the WM_DESTROY message is
received. The actual drawing is done whenever a WM_PAINT message is
received.
****************************************************************************/
long FAR PASCAL MainWndProc(hWnd, message, wParam, lParam)
HWND hWnd;
unsigned message;
WORD wParam;
LONG lParam;
{
FARPROC lpProcAbout;
HDC hDC; /* display-context variable */
PAINTSTRUCT ps; /* paint structure */
RECT rcTextBox; /* rectangle around the text */
HPEN hOldPen; /* old pen handle */
switch (message) {
case WM_COMMAND:
if (wParam == IDM_ABOUT) {
lpProcAbout = MakeProcInstance(About, hInst);
DialogBox(hInst,
"AboutBox",
hWnd,
lpProcAbout);
FreeProcInstance(lpProcAbout);
break;
}
else
return (DefWindowProc(hWnd, message, wParam, lParam));
case WM_CREATE:
/* Create the brush objects */
hRedBrush = CreateSolidBrush(RGB(255, 0, 0));
hGreenBrush = CreateSolidBrush(RGB( 0, 255, 0));
hBlueBrush = CreateSolidBrush(RGB( 0, 0, 255));
/* Create the "---" pen */
hDashPen = CreatePen(PS_DASH, /* style */
1, /* width */
RGB(0, 0, 0)); /* color */
/* Create the "..." pen */
hDotPen = CreatePen(2, /* style */
1, /* width */
RGB(0, 0, 0)); /* color */
break;
case WM_PAINT:
{
TEXTMETRIC textmetric;
int nDrawX;
int nDrawY;
char szText[300];
/* Set up a display context to begin painting */
hDC = BeginPaint (hWnd, &ps);
/* Get the size characteristics of the current font. */
/* This information will be used for determining the */
/* vertical spacing of text on the screen. */
GetTextMetrics (hDC, &textmetric);
/* Initialize drawing position to 1/4 inch from the top */
/* and from the left of the top, left corner of the */
/* client area of the main windows. */
nDrawX = GetDeviceCaps (hDC, LOGPIXELSX) / 4; /* 1/4 inch *
nDrawY = GetDeviceCaps (hDC, LOGPIXELSY) / 4; /* 1/4 inch *
/* Send characters to the screen. After displaying each */
/* line of text, advance the vertical position for the */
/* next line of text. The pixel distance between the top */
/* of each line of text is equal to the standard height of */
/* the font characters (tmHeight), plus the standard */
/* amount of spacing (tmExternalLeading) between adjacent */
/* lines. */
strcpy (szText, "These characters are being painted using ");
TextOut (hDC, nDrawX, nDrawY, szText, strlen (szText));
nDrawY += textmetric.tmExternalLeading + textmetric.tmHeight;
strcpy (szText, "the TextOut() function, which is fast and ")
TextOut (hDC, nDrawX, nDrawY, szText, strlen (szText));
nDrawY += textmetric.tmExternalLeading + textmetric.tmHeight;
strcpy (szText, "allows programmer control of placement and "
TextOut (hDC, nDrawX, nDrawY, szText, strlen (szText));
nDrawY += textmetric.tmExternalLeading + textmetric.tmHeight;
strcpy (szText, "formatting details. However, TextOut() ");
TextOut (hDC, nDrawX, nDrawY, szText, strlen (szText));
nDrawY += textmetric.tmExternalLeading + textmetric.tmHeight;
strcpy (szText, "does not provide any automatic formatting.")
TextOut (hDC, nDrawX, nDrawY, szText, strlen (szText));
nDrawY += textmetric.tmExternalLeading + textmetric.tmHeight;
/* Put text in a 5-inch by 1-inch rectangle and display it. *
/* First define the size of the rectangle around the text *
nDrawY += GetDeviceCaps (hDC, LOGPIXELSY) / 4; /* 1/4 inch *
SetRect (
&rcTextBox
, nDrawX
, nDrawY
, nDrawX + (5 * GetDeviceCaps (hDC, LOGPIXELSX)) /* 5" */
, nDrawY + (1 * GetDeviceCaps (hDC, LOGPIXELSY)) /* 1" */
);
/* Draw the text within the bounds of the above rectangle */
strcpy (szText, "This text is being displayed with a single "
"call to DrawText(). DrawText() isn't as fast "
"as TextOut(), and it is somewhat more "
"constrained, but it provides numerous optional "
"formatting features, such as the centering and "
"line breaking used in this example.");
DrawText (
hDC
, szText
, strlen (szText)
, &rcTextBox
, DT_CENTER | DT_EXTERNALLEADING | DT_NOCLIP
| DT_NOPREFIX | DT_WORDBREAK
);
/* Paint the next object immediately below the bottom of *
/* the above rectangle in which the text was drawn. *
nDrawY = rcTextBox.bottom;
/* The (x,y) pixel coordinates of the objects about to be *
/* drawn are below, and to the right of, the current *
/* coordinate (nDrawX,nDrawY). *
/* Draw a red rectangle.. */
hOldBrush = SelectObject(hDC, hRedBrush);
Rectangle (
hDC
, nDrawX
, nDrawY
, nDrawX + 50
, nDrawY + 30
);
/* Draw a green ellipse */
SelectObject(hDC, hGreenBrush);
Ellipse (
hDC
, nDrawX + 150
, nDrawY
, nDrawX + 150 + 50
, nDrawY + 30
);
/* Draw a blue pie shape */
SelectObject(hDC, hBlueBrush);
Pie (
hDC
, nDrawX + 300
, nDrawY
, nDrawX + 300 + 50
, nDrawY + 50
, nDrawX + 300 + 50
, nDrawY
, nDrawX + 300 + 50
, nDrawY + 50
);
nDrawY += 50;
/* Restore the old brush */
SelectObject(hDC, hOldBrush);
/* Select a "---" pen, save the old value */
nDrawY += GetDeviceCaps (hDC, LOGPIXELSY) / 4; /* 1/4 inch *
hOldPen = SelectObject(hDC, hDashPen);
/* Move to a specified point */
MoveTo(hDC, nDrawX, nDrawY);
/* Draw a line */
LineTo(hDC, nDrawX + 350, nDrawY);
/* Select a "..." pen */
SelectObject(hDC, hDotPen);
/* Draw an arc connecting the line */
Arc (
hDC
, nDrawX
, nDrawY - 20
, nDrawX + 350
, nDrawY + 20
, nDrawX
, nDrawY
, nDrawX + 350
, nDrawY
);
/* Restore the old pen */
SelectObject(hDC, hOldPen);
/* Tell Windows you are done painting */
EndPaint (hWnd, &ps);
}
break;
case WM_DESTROY:
DeleteObject(hRedBrush);
DeleteObject(hGreenBrush);
DeleteObject(hBlueBrush);
DeleteObject(hDashPen);
DeleteObject(hDotPen);
PostQuitMessage(0);
break;
default:
return (DefWindowProc(hWnd, message, wParam, lParam));
}
return (NULL);
}
/****************************************************************************
FUNCTION: About(HWND, unsigned, WORD, LONG)
PURPOSE: Processes messages for "About" dialog box
MESSAGES:
WM_INITDIALOG - initialize dialog box
WM_COMMAND - Input received
****************************************************************************/
BOOL FAR PASCAL About(hDlg, message, wParam, lParam)
HWND hDlg;
unsigned message;
WORD wParam;
LONG lParam;
{
switch (message) {
case WM_INITDIALOG:
return (TRUE);
case WM_COMMAND:
if (wParam == IDOK
|| wParam == IDCANCEL) {
EndDialog(hDlg, TRUE);
return (TRUE);
}
break;
}
return (FALSE);
}
OWNCOMBO.C
CD-ROM Disc Path: \SAMPCODE\WIN_SDK\OWNCOMBO\OWNCOMBO.C
/***************************************************************************
* *
* PROGRAM : OwnCombo.c *
* *
* PURPOSE : Illustrates the use of functions and messages for *
* combo boxes and owner-draw control styles. *
* *
* FUNCTIONS : WinMain - Creates the app. window and *
* enters the message loop. *
* *
* OwnComboInit - Registers the main window class *
* *
* About - Dialog function for the About *
* dialog. *
* *
* OwnComboWndProc - Window function for app. It *
* handles the menu selections *
* and processes the other window *
* messages. *
* *
* DrawEntireItem - Handles the drawing of a list *
* list box or combo box item. *
* *
* HandleSelectionState - Handles the selecting/deselect- *
* ing of a list box or combo box *
* item. *
* *
* HandleFocusState - Handles the getting/losing of *
* the input focus by a list box *
* *
* ListBoxExample - Dialog function for the *
* owner-draw list box example. *
* *
* ComboBoxExample - Dialog function for the text *
* combo dialog. *
* *
* OwnerComboBoxExample - Dialog fubction for the drop- *
* down-list combobox with *
* ownerdraw. *
* *
***************************************************************************/
#include "windows.h"
#include "owncombo.h"
HANDLE hInst;
/****************************************************************************
* *
* FUNCTION : WinMain(HANDLE, HANDLE, LPSTR, int) *
* *
* PURPOSE : Creates the app. window and enters the message loop. *
* *
****************************************************************************
int PASCAL WinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow)
HANDLE hInstance, hPrevInstance;
LPSTR lpCmdLine;
int nCmdShow;
{
HWND hWnd;
MSG msg;
if (!hPrevInstance)
if (!OwnComboInit (hInstance))
return (NULL);
hInst = hInstance;
/* Create the app. window */
hWnd = CreateWindow ("owncombo",
"Owner-draw & Combo Box Example",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
(HWND) NULL,
NULL,
hInstance,
(LPSTR) NULL);
if (!hWnd)
return (NULL);
ShowWindow (hWnd, nCmdShow);
while (GetMessage (&msg, NULL, NULL, NULL)){
TranslateMessage (&msg);
DispatchMessage (&msg);
}
return(msg.wParam);
}
/****************************************************************************
* *
* FUNCTION : OwnComboInit (hInstance) *
* *
* PURPOSE : Registers the main window class. *
* *
* RETURNS : TRUE - if RegisterClass () succeeds. *
* FALSE - if RegisterClass () fails. *
* *
****************************************************************************
BOOL NEAR PASCAL OwnComboInit (hInstance)
HANDLE hInstance;
{
HANDLE hMemory;
PWNDCLASS pWndClass;
BOOL bSuccess;
/* Allocate for and fill class structure. */
hMemory = LocalAlloc (LPTR, sizeof (WNDCLASS));
pWndClass = (PWNDCLASS) LocalLock (hMemory);
pWndClass->style = NULL;
pWndClass->lpfnWndProc = OwnComboWndProc;
pWndClass->hInstance = hInstance;
pWndClass->hIcon = LoadIcon (hInstance, "owncombo");
pWndClass->hCursor = LoadCursor (NULL, IDC_ARROW);
pWndClass->hbrBackground = GetStockObject (WHITE_BRUSH);
pWndClass->lpszMenuName = (LPSTR) "OwnComboMenu",
pWndClass->lpszClassName = (LPSTR) "owncombo";
bSuccess = RegisterClass (pWndClass);
LocalUnlock (hMemory);
LocalFree (hMemory);
return (bSuccess);
}
/****************************************************************************
* *
* FUNCTION : About (hDlg,message, wParam, lParam) *
* *
* PURPOSE : Dialog function for the About... dialog. *
* *
****************************************************************************
BOOL FAR PASCAL About (hDlg, message, wParam, lParam)
HWND hDlg;
unsigned message;
WORD wParam;
LONG lParam;
{
switch (message){
case WM_INITDIALOG:
return(TRUE);
case WM_COMMAND:
if (wParam == IDOK){
EndDialog (hDlg,NULL);
return(FALSE);
}
break;
default:
break;
}
return(FALSE);
}
/****************************************************************************
* *
* FUNCTION : OwnComboWndProc(hWnd, message, wParam, lParam) *
* *
* PURPOSE : Window function for the app. It handles menu selections *
* and processes window WM_ messages. *
* *
****************************************************************************
long FAR PASCAL OwnComboWndProc (hWnd, message, wParam, lParam)
HWND hWnd;
unsigned message;
WORD wParam;
LONG lParam;
{
FARPROC lpProc;
HMENU hMenu;
LPDRAWITEMSTRUCT dis;
RECT rc;
switch (message){
case WM_COMMAND:
switch (wParam){
case IDM_EXIT:
DestroyWindow (hWnd);
break;
case IDM_ABOUT:
/* Bring up the about box */
lpProc = MakeProcInstance (About, hInst);
DialogBox (hInst,
"AboutBox",
hWnd,
lpProc);
FreeProcInstance (lpProc);
break;
case IDM_LISTBOX:
/* Bring up the list box example */
lpProc = MakeProcInstance (ListBoxExample, hInst);
DialogBox (hInst,
"ListBoxDialog",
hWnd,
lpProc);
FreeProcInstance (lpProc);
break;
case IDM_MULTILISTBOX:
/* Bring up the multiple selection list box example */
lpProc = MakeProcInstance (ListBoxExample, hInst);
DialogBox (hInst,
"MultiListBoxDialog",
hWnd,
lpProc);
FreeProcInstance (lpProc);
break;
case IDM_COMBOBOX:
/* Bring up the combo box example */
lpProc = MakeProcInstance (ComboBoxExample, hInst);
DialogBox (hInst,
"ComboBoxDialog",
hWnd,
lpProc);
FreeProcInstance (lpProc);
break;
case IDM_OWNERCOMBOBOX:
/* Bring up the owner-draw dropdown list box example */
lpProc = MakeProcInstance (OwnerComboBoxExample, hInst);
DialogBox (hInst,
"OwnerComboBoxDialog",
hWnd,
lpProc);
FreeProcInstance (lpProc);
break;
}
break;
case WM_DESTROY:
PostQuitMessage (0);
break;
default:
return(DefWindowProc(hWnd, message, wParam, lParam));
}
return(NULL);
}
/****************************************************************************
* *
* FUNCTION : HandleSelectionState(LPDRAWITEMSTRUCT, int) *
* *
* PURPOSE : Handles a change in an item selection state. If an item is *
* selected, a black rectangular frame is drawn around that *
* item; if an item is de-selected, the frame is removed. *
* *
* COMMENT : The black selection frame is slightly larger than the gray *
* focus frame so they won't paint over each other. *
* *
****************************************************************************
void FAR PASCAL HandleSelectionState(lpdis, inflate)
LPDRAWITEMSTRUCT lpdis;
int inflate;
{
RECT rc;
HBRUSH hbr;
/* Resize rectangle to place selection frame outside of the focus
* frame and the item.
*/
CopyRect ((LPRECT)&rc, (LPRECT)&lpdis->rcItem);
InflateRect ((LPRECT)&rc, inflate, inflate);
if (lpdis->itemState & ODS_SELECTED)
{
/* selecting item -- paint a black frame */
hbr = GetStockObject(BLACK_BRUSH);
}
else
{
/* de-selecting item -- remove frame */
hbr = CreateSolidBrush(GetSysColor(COLOR_WINDOW));
}
FrameRect(lpdis->hDC, (LPRECT)&rc, hbr);
DeleteObject (hbr);
}
/****************************************************************************
* *
* FUNCTION : HandleFocusState(LPDRAWITEMSTRUCT, int) *
* *
* PURPOSE : Handle a change in item focus state. If an item gains the *
* input focus, a gray rectangular frame is drawn around that *
* item; if an item loses the input focus, the gray frame is *
* removed. *
* *
* COMMENT : The gray focus frame is slightly smaller than the black *
* selection frame so they won't paint over each other. *
* *
****************************************************************************
void FAR PASCAL HandleFocusState(lpdis, inflate)
LPDRAWITEMSTRUCT lpdis;
int inflate;
{
RECT rc;
HBRUSH hbr;
/* Resize rectangle to place focus frame between the selection
* frame and the item.
*/
CopyRect ((LPRECT)&rc, (LPRECT)&lpdis->rcItem);
InflateRect ((LPRECT)&rc, inflate, inflate);
if (lpdis->itemState & ODS_FOCUS)
{
/* gaining input focus -- paint a gray frame */
hbr = GetStockObject(GRAY_BRUSH);
}
else
{
/* losing input focus -- remove (paint over) frame */
hbr = CreateSolidBrush(GetSysColor(COLOR_WINDOW));
}
FrameRect(lpdis->hDC, (LPRECT)&rc, hbr);
DeleteObject (hbr);
}
/****************************************************************************
* *
* FUNCTION : DrawEntireItem(LPDRAWITEMSTRUCT, int) *
* *
* PURPOSE : Draws an item and frames it with a selection frame and/or *
* a focus frame when appropriate. *
* *
****************************************************************************
void FAR PASCAL DrawEntireItem(lpdis, inflate)
LPDRAWITEMSTRUCT lpdis;
int inflate;
{
RECT rc;
HBRUSH hbr;
/* Resize rectangle to leave space for frames */
CopyRect ((LPRECT)&rc, (LPRECT)&lpdis->rcItem);
InflateRect ((LPRECT)&rc, inflate, inflate);
/* Create a brush using the value in the item data field (this value
* was initialized when we added the item to the list/combo box using
* LB_ADDSTRING/CB_ADDSTRING) and draw the color in the list/combo box.
*/
hbr = CreateSolidBrush (lpdis->itemData);
FillRect (lpdis->hDC, (LPRECT)&rc, hbr);
DeleteObject (hbr);
/* Draw or erase appropriate frames */
HandleSelectionState(lpdis, inflate + 4);
HandleFocusState(lpdis, inflate + 2);
}
/****************************************************************************
* *
* FUNCTION : ListBoxExample (hDlg, message, wParam, lParam) *
* *
* PURPOSE : Dialog function for the owner-draw list box example. *
* It sets up the example dialog with the owner-draw list box,*
* adds the colors to the list box, and handles setting the *
* selection and focus for the items. *
* *
****************************************************************************
BOOL FAR PASCAL ListBoxExample (hDlg, message, wParam, lParam)
HWND hDlg;
unsigned message;
WORD wParam;
LONG lParam;
{
LPDRAWITEMSTRUCT lpdis;
LPMEASUREITEMSTRUCT lpmis;
/* Vars for WM_DRAWITEM */
RECT rc;
HBRUSH hbr;
switch (message){
case WM_COMMAND:
switch (wParam){
case IDOK:
EndDialog (hDlg, NULL);
return (TRUE);
break;
/* Clicking any of these buttons adds the corresponding color
* to the list box. The application-supplied data is the RGB
* value for the color to be drawn in the listbox.
*/
case ID_BLACK:
SendMessage (GetDlgItem (hDlg, ID_LISTBOX),
LB_ADDSTRING,
0,
RGB (0,0,0));
return(TRUE);
break;
case ID_RED:
SendMessage (GetDlgItem (hDlg, ID_LISTBOX),
LB_ADDSTRING,
0,
RGB (255,0,0));
return(TRUE);
break;
case ID_BLUE:
SendMessage (GetDlgItem (hDlg, ID_LISTBOX),
LB_ADDSTRING,
0,
RGB (0,0,255));
return(TRUE);
break;
case ID_GREEN:
SendMessage (GetDlgItem (hDlg, ID_LISTBOX),
LB_ADDSTRING,
0,
RGB (0,255,0));
return(TRUE);
break;
default:
return(FALSE);
break;
}
case WM_DRAWITEM:
/* Get pointer to the DRAWITEMSTRUCT */
lpdis = (LPDRAWITEMSTRUCT)lParam;
if (lpdis->itemID == -1)
{
/* We have a request to draw an item in the list box, yet there
* are no list box items. This is sent when the user TABS into
* an empty list box or an empty list box gets the focus. We
* have to indicate (somehow) that this owner-draw list box has
* the focus. We do it in response to this message. Note that
* lpdis->itemData field would be invalid in this instance so
* we can't allow it to fall into our standard routines.
*/
HandleFocusState(lpdis, -5);
}
else
{
switch (lpdis->itemAction)
{
case ODA_DRAWENTIRE:
DrawEntireItem(lpdis, -7);
break;
case ODA_SELECT:
HandleSelectionState(lpdis, -3);
break;
case ODA_FOCUS:
HandleFocusState(lpdis, -5);
break;
}
}
/* Return TRUE meaning that we processed this message. */
return(TRUE);
break;
case WM_MEASUREITEM:
lpmis = (LPMEASUREITEMSTRUCT)lParam;
/* All the items are the same height since the list box style is
* LBS_OWNERDRAWFIXED
*/
lpmis->itemHeight = 30;
break;
case WM_CLOSE:
EndDialog(hDlg, NULL);
return(TRUE);
break;
default:
return(FALSE);
}
return(TRUE);
}
/****************************************************************************
* *
* FUNCTION : ComboBoxExample(hWnd, message, wParam, lParam) *
* *
* PURPOSE : Dialog function for the text combo dialog. The push buttons*
* send various messages to the combo box and the edit control*
* when selected. They allow the user to vary data sent with *
* each message. *
* *
****************************************************************************
BOOL FAR PASCAL ComboBoxExample(hDlg, message, wParam, lParam)
HWND hDlg;
unsigned message;
WORD wParam;
LONG lParam;
{
HWND hWndCombo; /* Handle to the combo box control */
/* in the dialog box window */
HWND hWndCheckBox; /* Handle to the Auto Check Box */
char strSingleEditLine[255]; /* Single line edit control input */
int wIndex, wCount;
/* Get handles to the Combo box and the Check box */
hWndCombo = GetDlgItem(hDlg, ID_COMBOBOX);
hWndCheckBox = GetDlgItem(hDlg, ID_STEPSBOX);
switch (message){
case WM_COMMAND:
switch (wParam){
case IDOK:
EndDialog (hDlg,NULL);
return(TRUE);
case ID_UNSLBUTTON:
/* Selecting this button unselects any selection in the
* combo box.
*/
SetDlgItemText (hDlg, ID_TEXT1, "");
SetDlgItemText (hDlg, ID_TEXT2, "");
wIndex = (WORD) SendMessage( hWndCombo, CB_GETCURSEL, NULL, 0L);
if (wIndex == CB_ERR)
MessageBox (hDlg, (LPSTR)"No Selection", NULL, MB_OK);
else
SendMessage (hWndCombo, CB_SETCURSEL, -1, 0L);
SetFocus (GetDlgItem (hDlg, ID_SINGLEEDIT));
break;
case ID_NUMSELBUTTON:
/* An integer value is taken from the edit control and an
* attempt is made to select a combo box entry having this
* index.
*/
SetDlgItemText (hDlg, ID_TEXT1, "");
SetDlgItemText (hDlg, ID_TEXT2, "");
wCount = (WORD) SendMessage (hWndCombo, CB_GETCOUNT, 0, 0L);
wIndex = (int) GetDlgItemInt (hDlg, ID_SINGLEEDIT, NULL, TRUE);
if (wIndex >= wCount)
MessageBox (hDlg, (LPSTR)"Bad Selection", NULL, MB_OK);
else
SendMessage(hWndCombo, CB_SETCURSEL, wIndex, 0L);
SetFocus (GetDlgItem (hDlg, ID_SINGLEEDIT));
break;
case ID_TXTSELBUTTON:
/* A text string is taken from the edit control and an
* attempt is made to select a combo box entry having the
* string as a prefix.
*/
SetDlgItemText (hDlg, ID_TEXT1, "");
SetDlgItemText (hDlg, ID_TEXT2, "");
GetDlgItemText (hDlg, ID_SINGLEEDIT,
(LPSTR)strSingleEditLine, 255);
wIndex = (WORD) SendMessage (hWndCombo,
CB_SELECTSTRING,
-1,
(LONG)(LPSTR)strSingleEditLine);
if (wIndex == CB_ERR)
MessageBox (hDlg, (LPSTR)"Bad Selection", NULL, MB_OK);
SetFocus (GetDlgItem (hDlg, ID_SINGLEEDIT));
break;
case ID_FNDSELBUTTON:
/* Searches for the text specified in the list of combo
* entries and returns the index (in combo box) of the
* first match. The index is displayed in the "Text1"
* field of the dialog.
*/
SetDlgItemText (hDlg, ID_TEXT1, "");
SetDlgItemText (hDlg, ID_TEXT2, "");
GetDlgItemText (hDlg,
ID_SINGLEEDIT,
(LPSTR)strSingleEditLine,
255);
wIndex = (WORD)SendMessage (hWndCombo,
CB_FINDSTRING,-1,
(LONG)(LPSTR)strSingleEditLine);
if (wIndex == CB_ERR)
MessageBox (hDlg, (LPSTR)"Bad Selection", NULL, MB_OK);
else
SetDlgItemInt (hDlg, ID_TEXT1, wIndex, FALSE);
SetFocus (GetDlgItem (hDlg, ID_SINGLEEDIT));
break;
case ID_CLRBUTTON:
/* Clears the combo box of all it's entries */
SetDlgItemText (hDlg, ID_TEXT1, "");
SetDlgItemText (hDlg, ID_TEXT2, "");
wCount = (WORD) SendMessage (hWndCombo, CB_GETCOUNT, 0, 0L);
if (!wCount)
MessageBox (hDlg, (LPSTR)"Already clear", NULL, MB_OK);
else{
SetDlgItemInt (hDlg, ID_TEXT1, wCount, TRUE);
SetDlgItemText (hDlg, ID_TEXT2, "Items cleared");
SendMessage (hWndCombo,CB_RESETCONTENT, 0, 0L);
}
SetFocus (GetDlgItem (hDlg,ID_SINGLEEDIT));
break;
case ID_ADDBUTTON:
/* Takes the string specified in the edit control and
* adds it to the combo box.
*/
SetDlgItemText (hDlg, ID_TEXT1, "");
SetDlgItemText (hDlg, ID_TEXT2, "");
GetDlgItemText (hDlg, ID_SINGLEEDIT, strSingleEditLine, 255);
SendMessage (hWndCombo,
CB_ADDSTRING,
0,
(LONG)(LPSTR) strSingleEditLine);
SetFocus (GetDlgItem (hDlg, ID_SINGLEEDIT));
break;
case ID_DELETEBUTTON:
/* Delete the currently selected item from the combo box. */
SetDlgItemText (hDlg, ID_TEXT1, "");
SetDlgItemText (hDlg, ID_TEXT2, "");
wIndex = (WORD) SendMessage (hWndCombo, CB_GETCURSEL, 0, 0L);
if (SendMessage (hWndCombo, CB_DELETESTRING, wIndex, 0L) == CB_ERR)
MessageBox (hDlg, (LPSTR)"No Selection", NULL, MB_OK);
else{
SetDlgItemText (hDlg, ID_TEXT1, "deleted index #");
SetDlgItemInt (hDlg, ID_TEXT2, wIndex, TRUE);
}
SetFocus (GetDlgItem (hDlg, ID_SINGLEEDIT));
break;
case ID_CBDIRBUTTON:
/* Appends a directory listing of the current directory
* to the combo box entries.
*/
SetDlgItemText (hDlg, ID_TEXT1, "");
SetDlgItemText (hDlg, ID_TEXT2, "");
wIndex = (WORD)SendMessage (hWndCombo,
CB_DIR,
0x10|0x4000,
(LONG)(LPSTR)"*.*");
SetFocus (GetDlgItem (hDlg, ID_SINGLEEDIT));
break;
case ID_CPYBUTTON:
/* Copies the currently selected item in the combo box to
* the edit control.
*/
SetDlgItemText (hDlg, ID_TEXT1, "");
SetDlgItemText (hDlg, ID_TEXT2, "");
wIndex = (WORD) SendMessage (hWndCombo, CB_GETCURSEL, 0, 0L);
if (wIndex == CB_ERR)
MessageBox(hDlg, (LPSTR)"No Selection", NULL, MB_OK);
else{
wCount = SendMessage (hWndCombo, CB_GETLBTEXTLEN, wIndex, 0L);
SendMessage (hWndCombo,
CB_GETLBTEXT,
wIndex,
(LONG)(LPSTR)strSingleEditLine);
SetDlgItemText(hDlg, ID_SINGLEEDIT,
(LPSTR)strSingleEditLine);
SetDlgItemText(hDlg, ID_TEXT1, "copied index #");
SetDlgItemInt(hDlg, ID_TEXT2, wIndex, TRUE);
}
SetFocus (GetDlgItem (hDlg, ID_SINGLEEDIT));
break;
/* When the combo notification box is checked, a message box
* is flashed showing what notification codes the combo box is
* returning to the app. in response to the messages sent by
* the buttons.
*/
case ID_COMBOBOX:
if (SendMessage (hWndCheckBox, BM_GETCHECK, 0, 0L)){
switch (HIWORD(lParam)){
case (WORD)CBN_ERRSPACE:
MessageBox (hDlg, (LPSTR)"CB Out of Space",
"CB MSG", MB_OK);
break;
case CBN_SELCHANGE:
MessageBox (hDlg, (LPSTR)"CB Sel Change",
"CB MSG", MB_OK);
break;
case CBN_DBLCLK:
MessageBox(hDlg, (LPSTR)"CB Double Click",
"CB MSG", MB_OK);
break;
case CBN_SETFOCUS:
SetDlgItemText(hDlg, ID_TEXT1, "CB SetFocus");
break;
case CBN_KILLFOCUS:
SetDlgItemText(hDlg, ID_TEXT1, "CB KillFocus");
break;
}
}
break;
default:
return(FALSE);
}
break;
case WM_CLOSE:
EndDialog(hDlg, NULL);
return(TRUE);
break;
default:
return(FALSE);
}
return(TRUE);
}
/****************************************************************************
* *
* FUNCTION : OwnerComboBoxExample(hWnd, message, wParam, lParam) *
* *
* PURPOSE : Dialog function for the dropdown list combo box with *
* owner-draw. *
* *
****************************************************************************
BOOL FAR PASCAL OwnerComboBoxExample (hDlg, message, wParam, lParam)
HWND hDlg;
unsigned message;
WORD wParam;
LONG lParam;
{
LPDRAWITEMSTRUCT lpdis;
LPMEASUREITEMSTRUCT lpmis;
/* Variables for WM_DRAWITEM */
RECT rc;
HBRUSH hbr;
switch (message){
case WM_COMMAND:
switch (wParam){
case IDOK:
EndDialog (hDlg, NULL);
return(TRUE);
break;
/* Clicking any of these buttons adds the corresponding color
* to the combo box. The application-supplied data is the RGB
* value for the color to be drawn in the listbox.
*/
case ID_BLACK:
SendMessage (GetDlgItem(hDlg, ID_LISTBOX),
CB_ADDSTRING,
0,
RGB (0,0,0));
return(TRUE);
break;
case ID_RED:
SendMessage (GetDlgItem (hDlg, ID_LISTBOX),
CB_ADDSTRING,
0,
RGB (255,0,0));
return(TRUE);
break;
case ID_BLUE:
SendMessage (GetDlgItem(hDlg, ID_LISTBOX),
CB_ADDSTRING,
0,
RGB (0,0,255));
return(TRUE);
break;
case ID_GREEN:
SendMessage (GetDlgItem(hDlg, ID_LISTBOX),
CB_ADDSTRING,
0,
RGB (0,255,0));
return(TRUE);
break;
default:
return(TRUE);
break;
}
case WM_DRAWITEM:
/* Get pointer to the DRAWITEMSTRUCT */
lpdis = (LPDRAWITEMSTRUCT)lParam;
if (lpdis->itemID == -1){
/* We have a request to draw an item in the combo box, yet there
* are no combo box items. This is sent when the user TABS into
* an empty combo box or an empty combo box gets the focus. We
* have to indicate (somehow) that this owner-draw combo box has
* the focus. We do it in response to this message. Note that
* lpdis->itemData field would be invalid in this instance so
* we can't allow it to fall into our standard routines.
*/
HandleFocusState(lpdis, -2);
}
else
{
switch (lpdis->itemAction)
{
case ODA_DRAWENTIRE:
DrawEntireItem(lpdis, -4);
break;
case ODA_SELECT:
HandleSelectionState(lpdis, 0);
break;
case ODA_FOCUS:
HandleFocusState(lpdis, -2);
break;
}
}
/* Return TRUE meaning that we processed this message. */
return(TRUE);
break;
case WM_MEASUREITEM:
lpmis = (LPMEASUREITEMSTRUCT)lParam;
/* All the items are the same height since the combo box is
* CBS_OWNERDRAWFIXED
*/
if (lpmis->itemID == -1){
/* If -1 for item, then we are setting the height of the
* always visible static item part of the dropdown combo box.
*/
lpmis->itemHeight = 25;
return(TRUE);
}
lpmis->itemHeight = 30;
break;
case WM_CLOSE:
EndDialog(hDlg, NULL);
return(TRUE);
break;
default:
return(FALSE);
}
return(TRUE);
}
PRINT.C
CD-ROM Disc Path: \SAMPCODE\WIN_SDK\SHOWDIB\PRINT.C
/****************************************************************************
* *
* MODULE : Print.c *
* *
* DESCRIPTION : Routines used for printing. *
* *
* FUNCTIONS : GetPrinterDC() - Gets default printer from WIN.INI and
* creates a DC for it. *
* *
* InitPrinting() - Initializes print job. *
* *
* TermPrinting() - Terminates print job. *
* *
* PrintDlgProc() - Dialog function for the "Cancel Printing" *
* dialog. *
* *
* AbortProc() - Peeks at message queue for messages from *
* the print dialog. *
* *
****************************************************************************
#include <windows.h>
#include <string.h>
#include "showdib.h"
FARPROC lpfnAbortProc = NULL;
FARPROC lpfnPrintDlgProc = NULL;
HWND hWndParent = NULL;
HWND hDlgPrint = NULL;
BOOL bError;
BOOL bUserAbort;
BOOL FAR PASCAL AbortProc (HDC, short);
BOOL FAR PASCAL PrintDlgProc (HWND, unsigned, WORD, DWORD);
#pragma alloc_text(_PRINT, AbortProc, PrintDlgProc)
/****************************************************************************
* *
* FUNCTION : GetPrinterDC() *
* *
* PURPOSE : Read WIN.INI for default printer and create a DC for it. *
* *
* RETURNS : A handle to the DC if successful or NULL otherwise. *
* *
****************************************************************************
HDC PASCAL GetPrinterDC()
{
static char szPrinter [80];
char *szDevice, *szDriver, *szOutput;
GetProfileString ("windows", "device", "", szPrinter, sizeof(szPrinter));
if ((szDevice = strtok (szPrinter, "," )) &&
(szDriver = strtok (NULL, ", ")) &&
(szOutput = strtok (NULL, ", ")))
return CreateDC (szDriver, szDevice, szOutput, NULL) ;
return NULL;
}
/****************************************************************************
* *
* FUNCTION : InitPrinting(HDC hDC, HWND hWnd, HANDLE hInst, LPSTR msg) *
* *
* PURPOSE : Makes preliminary driver calls to set up print job. *
* *
* RETURNS : TRUE - if successful. *
* FALSE - otherwise. *
* *
****************************************************************************
BOOL PASCAL InitPrinting(HDC hDC, HWND hWnd, HANDLE hInst, LPSTR msg)
{
bError = FALSE; /* no errors yet */
bUserAbort = FALSE; /* user hasn't aborted */
hWndParent = hWnd; /* save for Enable at Term time */
lpfnPrintDlgProc = MakeProcInstance (PrintDlgProc, hInst);
lpfnAbortProc = MakeProcInstance (AbortProc, hInst);
hDlgPrint = CreateDialog (hInst, "PRTDLG", hWndParent, lpfnPrintDlgProc);
if (!hDlgPrint)
return FALSE;
SetWindowText (hDlgPrint, msg);
EnableWindow (hWndParent, FALSE); /* disable parent */
if ((Escape (hDC, SETABORTPROC, 0, (LPSTR)lpfnAbortProc, NULL) > 0) &&
(Escape (hDC, STARTDOC, lstrlen(msg), msg, NULL) > 0))
bError = FALSE;
else
bError = TRUE;
/* might want to call the abort proc here to allow the user to
* abort just before printing begins */
return TRUE;
}
/****************************************************************************
* *
* FUNCTION : TermPrinting(HDC hDC) *
* *
* PURPOSE : Terminates print job. *
* *
****************************************************************************
void PASCAL TermPrinting(HDC hDC)
{
if (!bError)
Escape(hDC, ENDDOC, 0, NULL, NULL);
if (bUserAbort)
Escape (hDC, ABORTDOC, 0, NULL, NULL) ;
else {
EnableWindow(hWndParent, TRUE);
DestroyWindow(hDlgPrint);
}
FreeProcInstance(lpfnAbortProc);
FreeProcInstance(lpfnPrintDlgProc);
}
/****************************************************************************
* *
* FUNCTION :PrintDlgProc (HWND, unsigned , WORD , DWORD ) *
* *
* PURPOSE :Dialog function for the "Cancel Printing" dialog. It sets *
* the abort flag if the user presses <Cancel>. *
* *
****************************************************************************
BOOL FAR PASCAL PrintDlgProc (HWND hDlg, unsigned iMessage, WORD wParam, DWOR
{
switch (iMessage) {
case WM_INITDIALOG:
EnableMenuItem (GetSystemMenu (hDlg, FALSE), SC_CLOSE, MF_GRAYED);
break;
case WM_COMMAND:
bUserAbort = TRUE;
EnableWindow (hWndParent, TRUE);
DestroyWindow (hDlg);
hDlgPrint = 0;
break;
default:
return FALSE;
}
return TRUE;
}
/****************************************************************************
* *
* FUNCTION :AbortProc (HDC hPrnDC, short nCode) *
* *
* PURPOSE :Checks message queue for messages from the "Cancel Printing"*
* dialog. If it sees a message, (this will be from a print *
* cancel command), it terminates. *
* *
* RETURNS :Inverse of Abort flag *
* *
****************************************************************************
BOOL FAR PASCAL AbortProc (HDC hPrnDC, short nCode)
{
MSG msg;
while (!bUserAbort && PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) {
if (!hDlgPrint || !IsDialogMessage(hDlgPrint, &msg)) {
TranslateMessage (&msg);
DispatchMessage (&msg);
}
}
return !bUserAbort;
}
PRNTFILE.C
CD-ROM Disc Path: \SAMPCODE\WIN_SDK\PRNTFILE\PRNTFILE.C
/****************************************************************************
PROGRAM: PrntFile.c
PURPOSE: Loads, saves, and edits text files
FUNCTIONS:
WinMain() - calls initialization function, processes message loop
InitApplication() - initializes window data and registers window
InitInstance() - saves instance handle and creates main window
MainWndProc() - processes messages
About() - processes messages for "About" dialog box
SaveAsDlg() - save file under different name
OpenDlg() - let user select a file, and open it.
UpdateListBox() - Update the list box of OpenDlg
ChangeDefExt() - Change the default extension
SeparateFile() - Separate filename and pathname
AddExt() - Add default extension
CheckFileName() - Check for wildcards, add extension if needed
SaveFile() - Save current file
QuerySaveFile() - Called when some action might lose current contents
SetNewBuffer() - Set new buffer for edit window
****************************************************************************/
#include "windows.h"
#include "prntfile.h"
HANDLE hInst;
HANDLE hAccTable; /* handle to accelerator tab
HWND hEditWnd; /* handle to edit window
HWND hwnd; /* handle to main window */
/* Additional includes needed for the fstat() function */
#include <sys\types.h>
#include <sys\stat.h>
char FileName[128];
char PathName[128];
char OpenName[128];
char DefPath[128];
char DefSpec[13] = "*.*";
char DefExt[] = ".txt";
char str[255];
HANDLE hEditBuffer; /* handle to editing buffer */
HANDLE hOldBuffer; /* old buffer handle */
HANDLE hHourGlass; /* handle to hourglass cursor
HANDLE hSaveCursor; /* current cursor handle */
int hFile; /* file handle */
int count; /* number of chars read or written
PSTR pBuffer; /* address of read/write buffer
OFSTRUCT OfStruct; /* information from OpenFile()
struct stat FileStatus; /* information from fstat() */
BOOL bChanges = FALSE; /* TRUE if the file is changed
BOOL bSaveEnabled = FALSE; /* TRUE if text in the edit buffer
PSTR pEditBuffer; /* address of the edit buffer
RECT Rect; /* dimension of the client window
char Untitled[] = /* default window title */
"Edit File - (untitled)";
/* Printer variables */
HDC hPr; /* handle for printer device context
int LineSpace; /* spacing between lines */
int LinesPerPage; /* lines per page */
int CurrentLine; /* current line */
int LineLength; /* line length */
DWORD dwLines; /* number of lines to print */
DWORD dwIndex; /* index into lines to print */
char pLine[128]; /* buffer to store lines before printing
TEXTMETRIC TextMetric; /* information about character size
BOOL bAbort; /* FALSE if user cancels printing */
HWND hAbortDlgWnd;
FARPROC lpAbortDlg, lpAbortProc;
/****************************************************************************
FUNCTION: WinMain(HANDLE, HANDLE, LPSTR, int)
PURPOSE: calls initialization function, processes message loop
****************************************************************************/
int PASCAL WinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow)
HANDLE hInstance;
HANDLE hPrevInstance;
LPSTR lpCmdLine;
int nCmdShow;
{
MSG msg;
if (!hPrevInstance)
if (!InitApplication(hInstance))
return (FALSE);
if (!InitInstance(hInstance, nCmdShow))
return (FALSE);
while (GetMessage(&msg, NULL, NULL, NULL)) {
/* Only translate message if it is not an accelerator message */
if (!TranslateAccelerator(hwnd, hAccTable, &msg)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return (msg.wParam);
}
/****************************************************************************
FUNCTION: InitApplication(HANDLE)
PURPOSE: Initializes window data and registers window class
****************************************************************************/
BOOL InitApplication(hInstance)
HANDLE hInstance;
{
WNDCLASS wc;
wc.style = NULL;
wc.lpfnWndProc = MainWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = "PrntFileMenu";
wc.lpszClassName = "PrntFileWClass";
return (RegisterClass(&wc));
}
/****************************************************************************
FUNCTION: InitInstance(HANDLE, int)
PURPOSE: Saves instance handle and creates main window
****************************************************************************/
BOOL InitInstance(hInstance, nCmdShow)
HANDLE hInstance;
int nCmdShow;
{
RECT Rect;
hInst = hInstance;
hAccTable = LoadAccelerators(hInst, "PrntFileAcc");
hwnd = CreateWindow(
"PrntFileWClass",
"PrntFile Sample Application",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
hInstance,
NULL
);
if (!hwnd)
return (FALSE);
GetClientRect(hwnd, (LPRECT) &Rect);
/* Create a child window */
hEditWnd = CreateWindow("Edit",
NULL,
WS_CHILD | WS_VISIBLE |
ES_MULTILINE |
WS_VSCROLL | WS_HSCROLL |
ES_AUTOHSCROLL | ES_AUTOVSCROLL,
0,
0,
(Rect.right-Rect.left),
(Rect.bottom-Rect.top),
hwnd,
IDC_EDIT, /* Child control i.d. */
hInst,
NULL);
if (!hEditWnd) {
DestroyWindow(hwnd);
return (NULL);
}
/* Get an hourglass cursor to use during file transfers */
hHourGlass = LoadCursor(NULL, IDC_WAIT);
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
return (TRUE);
}
/****************************************************************************
FUNCTION: MainWndProc(HWND, unsigned, WORD, LONG)
PURPOSE: Processes messages
MESSAGES:
WM_COMMAND - application menu (About dialog box)
WM_DESTROY - destroy window
WM_SIZE - window size has changed
WM_QUERYENDSESSION - willing to end session?
WM_ENDSESSION - end Windows session
WM_CLOSE - close the window
WM_SIZE - window resized
COMMENTS:
Adds printing capability to the EDITFILE program. Printing request
is sent as an IDM_PRINT message.
Before the printing operation begins, a modeless dialog box is
created to allow the user to abort the printing operation. This
dialog box remains active until the print job is completed, or the
user cancels the print operation.
****************************************************************************/
long FAR PASCAL MainWndProc(hWnd, message, wParam, lParam)
HWND hWnd;
unsigned message;
WORD wParam;
LONG lParam;
{
FARPROC lpProcAbout, lpOpenDlg, lpSaveAsDlg;
int Success; /* return value from SaveAsDlg()
int IOStatus; /* result of file i/o */
int nPageSize; /* vert. resolution of printer device */
switch (message) {
case WM_COMMAND:
switch (wParam) {
case IDM_ABOUT:
lpProcAbout = MakeProcInstance(About, hInst);
DialogBox(hInst, "AboutBox", hWnd, lpProcAbout);
FreeProcInstance(lpProcAbout);
break;
case IDM_NEW:
/* If current file has been modified, query user about
* saving it.
*/
if (!QuerySaveFile(hWnd))
return (NULL);
/* bChanges is set to FALSE to indicate there have been
* no changes since the last file save.
*/
bChanges = FALSE;
FileName[0] = 0;
/* Update the edit buffer */
SetNewBuffer(hWnd, NULL, Untitled);
break;
case IDM_OPEN:
if (!QuerySaveFile(hWnd))
return (NULL);
lpOpenDlg = MakeProcInstance((FARPROC) OpenDlg, hInst);
/* Open the file and get its handle */
hFile = DialogBox(hInst, "Open", hWnd, lpOpenDlg);
FreeProcInstance(lpOpenDlg);
if (!hFile)
return (NULL);
/* Allocate edit buffer to the size of the file + 1 */
hEditBuffer =
LocalAlloc(LMEM_MOVEABLE | LMEM_ZEROINIT,
(WORD)FileStatus.st_size+1);
if (!hEditBuffer) {
MessageBox(hWnd, "Not enough memory.",
NULL, MB_OK | MB_ICONHAND);
return (NULL);
}
hSaveCursor = SetCursor(hHourGlass);
pEditBuffer = LocalLock(hEditBuffer);
IOStatus = read(hFile, pEditBuffer, FileStatus.st_size);
close(hFile);
/* # bytes read must equal file size */
if (IOStatus != (int)FileStatus.st_size) {
sprintf(str, "Error reading %s.", FileName);
SetCursor(hSaveCursor); /* Remove the hourglass
MessageBox(hWnd, str, NULL, MB_OK | MB_ICONEXCLAMATIO
}
LocalUnlock(hEditBuffer);
/* Set up a new buffer and window title */
sprintf(str, "PrntFile - %s", FileName);
SetNewBuffer(hWnd, hEditBuffer, str);
SetCursor(hSaveCursor); /* restore the cursor
break;
case IDM_SAVE:
/* If there is no filename, use the saveas command to get
* one. Otherwise, save the file using the current
* filename.
*/
if (!FileName[0])
goto saveas;
if (bChanges)
SaveFile(hWnd);
break;
case IDM_SAVEAS:
saveas:
lpSaveAsDlg = MakeProcInstance(SaveAsDlg, hInst);
/* Call the SaveAsDlg() function to get the new filename
Success = DialogBox(hInst, "SaveAs", hWnd, lpSaveAsDlg);
FreeProcInstance(lpSaveAsDlg);
/* If successful, update the window title, save the file
if (Success == IDOK) {
sprintf(str, "PrntFile - %s", FileName);
SetWindowText(hWnd, str);
SaveFile(hWnd);
}
break; /* User canceled
case IDM_PRINT:
hSaveCursor = SetCursor(hHourGlass);
hPr = GetPrinterDC();
if (!hPr) {
sprintf(str, "Cannot print %s", FileName);
MessageBox(hWnd, str, NULL, MB_OK | MB_ICONHAND);
return (NULL);
}
lpAbortDlg = MakeProcInstance(AbortDlg, hInst);
lpAbortProc = MakeProcInstance(AbortProc, hInst);
/* Define the abort function */
Escape(hPr, SETABORTPROC, NULL,
(LPSTR) (long) lpAbortProc,
(LPSTR) NULL);
if (Escape(hPr, STARTDOC, 4, "PrntFile text",
(LPSTR) NULL) < 0) {
MessageBox(hWnd, "Unable to start print job",
NULL, MB_OK | MB_ICONHAND);
FreeProcInstance(lpAbortDlg);
FreeProcInstance(lpAbortProc);
DeleteDC(hPr);
}
bAbort = FALSE; /* Clears the abort flag */
/* Create the Abort dialog box (modeless) */
hAbortDlgWnd = CreateDialog(hInst, "AbortDlg",
hWnd, lpAbortDlg);
if (!hAbortDlgWnd) {
SetCursor(hSaveCursor); /* Remove the hourglass
MessageBox(hWnd, "NULL Abort window handle",
NULL, MB_OK | MB_ICONHAND);
return (FALSE);
}
/* Now show Abort dialog */
ShowWindow (hAbortDlgWnd, SW_NORMAL);
/* Disable the main window to avoid reentrancy problems *
EnableWindow(hWnd, FALSE);
SetCursor(hSaveCursor); /* Remove the hourglass */
/* Since you may have more than one line, you need to
* compute the spacing between lines. You can do that by
* retrieving the height of the characters you are printi
* and advancing their height plus the recommended extern
* leading height.
*/
GetTextMetrics(hPr, &TextMetric);
LineSpace = TextMetric.tmHeight +
TextMetric.tmExternalLeading;
/* Since you may have more lines than can fit on one
* page, you need to compute the number of lines you can
* print per page. You can do that by retrieving the
* dimensions of the page and dividing the height
* by the line spacing.
*/
nPageSize = GetDeviceCaps (hPr, VERTRES);
LinesPerPage = nPageSize / LineSpace - 1;
/* You can output only one line at a time, so you need a
* count of the number of lines to print. You can retrie
* the count sending the EM_GETLINECOUNT message to the e
* control.
*/
dwLines = SendMessage(hEditWnd, EM_GETLINECOUNT, 0, 0L);
/* Keep track of the current line on the current page */
CurrentLine = 1;
/* One way to output one line at a time is to retrieve
* one line at a time from the edit control and write it
* using the TextOut function. For each line you need to
* advance one line space. Also, you need to check for t
* end of the page and start a new page if necessary.
*/
for (dwIndex = IOStatus = 0; dwIndex < dwLines; dwIndex++
pLine[0] = 128; /* Maximum buffer size
pLine[1] = 0;
LineLength = SendMessage(hEditWnd, EM_GETLINE,
(WORD)dwIndex, (LONG)((LPSTR)pLine));
TextOut(hPr, 0, CurrentLine*LineSpace,
(LPSTR)pLine, LineLength);
if (++CurrentLine > LinesPerPage ) {
CurrentLine = 1;
IOStatus = Escape(hPr, NEWFRAME, 0, 0L, 0L);
if (IOStatus<0 || bAbort)
break;
}
}
if (IOStatus >= 0 && !bAbort) {
Escape(hPr, NEWFRAME, 0, 0L, 0L);
Escape(hPr, ENDDOC, 0, 0L, 0L);
}
EnableWindow(hWnd, TRUE);
/* Destroy the Abort dialog box */
DestroyWindow(hAbortDlgWnd);
FreeProcInstance(lpAbortDlg);
FreeProcInstance(lpAbortProc);
DeleteDC(hPr);
break;
/* edit menu commands */
case IDM_UNDO:
case IDM_CUT:
case IDM_COPY:
case IDM_PASTE:
case IDM_CLEAR:
MessageBox (
GetFocus(),
"Command not implemented",
"PrntFile Sample Application",
MB_ICONASTERISK | MB_OK);
break;
case IDM_EXIT:
QuerySaveFile(hWnd);
DestroyWindow(hWnd);
break;
case IDC_EDIT:
if (HIWORD (lParam) == EN_ERRSPACE) {
MessageBox (
GetFocus ()
, "Out of memory."
, "PrntFile Sample Application"
, MB_ICONHAND | MB_OK
);
}
break;
}
break;
case WM_SETFOCUS:
SetFocus (hEditWnd);
break;
case WM_SIZE:
MoveWindow(hEditWnd, 0, 0, LOWORD(lParam), HIWORD(lParam), TRUE);
break;
case WM_QUERYENDSESSION: /* message: to end the session?
return (QuerySaveFile(hWnd));
case WM_CLOSE: /* message: close the window
if (QuerySaveFile(hWnd))
DestroyWindow(hWnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return (DefWindowProc(hWnd, message, wParam, lParam));
}
return (NULL);
}
/****************************************************************************
FUNCTION: SaveAsDlg(HWND, unsigned, WORD, LONG)
PURPOSE: Allows user to change name to save file to
COMMENTS:
This will initialize the window class if it is the first time this
application is run. It then creates the window, and processes the
message loop until a PostQuitMessage is received. It exits the
application by returning the value passed by the PostQuitMessage.
****************************************************************************/
int FAR PASCAL SaveAsDlg(hDlg, message, wParam, lParam)
HWND hDlg;
unsigned message;
WORD wParam;
LONG lParam;
{
char TempName[128];
switch (message) {
case WM_INITDIALOG:
/* If no filename is entered, don't allow the user to save to it
if (!FileName[0])
bSaveEnabled = FALSE;
else {
bSaveEnabled = TRUE;
/* Process the path to fit within the IDC_PATH field */
DlgDirList(hDlg, DefPath, NULL, IDC_PATH, 0x4010);
/* Send the current filename to the edit control */
SetDlgItemText(hDlg, IDC_EDIT, FileName);
/* Accept all characters in the edit control */
SendDlgItemMessage(hDlg, IDC_EDIT, EM_SETSEL, 0,
MAKELONG(0, 0x7fff));
}
/* Enable or disable the save control depending on whether the
* filename exists.
*/
EnableWindow(GetDlgItem(hDlg, IDOK), bSaveEnabled);
/* Set the focus to the edit control within the dialog box */
SetFocus(GetDlgItem(hDlg, IDC_EDIT));
return (FALSE); /* FALSE since Focus was changed
case WM_COMMAND:
switch (wParam) {
case IDC_EDIT:
/* If there was previously no filename in the edit
* control, then the save control must be enabled as soon
* a character is entered.
*/
if (HIWORD(lParam) == EN_CHANGE && !bSaveEnabled)
EnableWindow(GetDlgItem(hDlg, IDOK), bSaveEnabled = TRUE)
return (TRUE);
case IDOK:
/* Get the filename from the edit control */
GetDlgItemText(hDlg, IDC_EDIT, TempName, 128);
/* If there are no wildcards, then separate the name into
* path and name. If a path was specified, replace the
* default path with the new path.
*/
if (CheckFileName(hDlg, FileName, TempName)) {
SeparateFile(hDlg, (LPSTR) str, (LPSTR) DefSpec,
(LPSTR) FileName);
if (str[0])
strcpy(DefPath, str);
/* Tell the caller a filename was selected */
EndDialog(hDlg, IDOK);
}
return (TRUE);
case IDCANCEL:
/* Tell the caller the user canceled the SaveAs function
EndDialog(hDlg, IDCANCEL);
return (TRUE);
}
break;
}
return (FALSE);
}
/****************************************************************************
FUNCTION: OpenDlg(HWND, unsigned, WORD, LONG)
PURPOSE: Let user select a file, and open it.
****************************************************************************/
HANDLE FAR PASCAL OpenDlg(hDlg, message, wParam, lParam)
HWND hDlg;
unsigned message;
WORD wParam;
LONG lParam;
{
WORD index;
PSTR pTptr;
HANDLE hFile;
switch (message) {
case WM_COMMAND:
switch (wParam) {
case IDC_LISTBOX:
switch (HIWORD(lParam)) {
case LBN_SELCHANGE:
/* If item is a directory name, append "*.*" */
if (DlgDirSelect(hDlg, str, IDC_LISTBOX)) {
strcat(str, DefSpec);
}
SetDlgItemText(hDlg, IDC_EDIT, str);
SendDlgItemMessage(hDlg,
IDC_EDIT,
EM_SETSEL,
NULL,
MAKELONG(0, 0x7fff));
break;
case LBN_DBLCLK:
goto openfile;
}
return (TRUE);
case IDOK:
openfile:
GetDlgItemText(hDlg, IDC_EDIT, OpenName, 128);
if (strchr(OpenName, '*') || strchr(OpenName, '?')) {
SeparateFile(hDlg, (LPSTR) str, (LPSTR) DefSpec,
(LPSTR) OpenName);
if (str[0])
strcpy(DefPath, str);
ChangeDefExt(DefExt, DefSpec);
UpdateListBox(hDlg);
return (TRUE);
}
if (!OpenName[0]) {
MessageBox(hDlg, "No filename specified.",
NULL, MB_OK | MB_ICONHAND);
return (TRUE);
}
AddExt(OpenName, DefExt);
/* Open the file */
if ((hFile = OpenFile(OpenName, (LPOFSTRUCT) &OfStruct,
OF_READ)) == -1) {
sprintf(str, "Error %d opening %s.",
OfStruct.nErrCode, OpenName);
MessageBox(hDlg, str, NULL,
MB_OK | MB_ICONHAND);
}
else {
/* Make sure there's enough room for the file */
fstat(hFile, &FileStatus);
if (FileStatus.st_size > MAXFILESIZE) {
sprintf(str,
"Not enough memory to load %s.\n%s exceeds %ld bytes.",
OpenName, OpenName, MAXFILESIZE);
MessageBox(hDlg, str, NULL,
MB_OK | MB_ICONHAND);
return (TRUE);
}
/* File is opened and there is enough room so return
* the handle to the caller.
*/
strcpy(FileName, OpenName);
EndDialog(hDlg, hFile);
return (TRUE);
}
return (TRUE);
case IDCANCEL:
/* strcpy(DefPath, str);
ChangeDefExt(DefExt, DefSpec);*/
EndDialog(hDlg, NULL);
return (TRUE);
}
break;
case WM_INITDIALOG: /* message: initialize
UpdateListBox(hDlg);
SetDlgItemText(hDlg, IDC_EDIT, DefSpec);
SendDlgItemMessage(hDlg, /* dialog handle */
IDC_EDIT, /* where to send message
EM_SETSEL, /* select characters
NULL, /* additional information
MAKELONG(0, 0x7fff)); /* entire contents */
SetFocus(GetDlgItem(hDlg, IDC_EDIT));
return (FALSE); /* Indicates the focus is set to a control */
}
return FALSE;
}
/****************************************************************************
FUNCTION: UpdateListBox(HWND);
PURPOSE: Update the list box of OpenDlg
****************************************************************************/
void UpdateListBox(hDlg)
HWND hDlg;
{
strcpy(str, DefPath);
strcat(str, DefSpec);
DlgDirList(hDlg, str, IDC_LISTBOX, IDC_PATH, 0x4010);
/* To ensure that the listing is made for a subdir. of
* current drive dir...
*/
if (!strchr (DefPath, ':'))
DlgDirList(hDlg, DefSpec, IDC_LISTBOX, IDC_PATH, 0x4010);
/* Remove the '..' character from path if it exists, since this
* will make DlgDirList move us up an additional level in the tree
* when UpdateListBox() is called again.
*/
if (strstr (DefPath, ".."))
DefPath[0] = '\0';
SetDlgItemText(hDlg, IDC_EDIT, DefSpec);
}
/****************************************************************************
FUNCTION: ChangeDefExt(PSTR, PSTR);
PURPOSE: Change the default extension
****************************************************************************/
void ChangeDefExt(Ext, Name)
PSTR Ext, Name;
{
PSTR pTptr;
pTptr = Name;
while (*pTptr && *pTptr != '.')
pTptr++;
if (*pTptr)
if (!strchr(pTptr, '*') && !strchr(pTptr, '?'))
strcpy(Ext, pTptr);
}
/****************************************************************************
FUNCTION: SeparateFile(HWND, LPSTR, LPSTR, LPSTR)
PURPOSE: Separate filename and pathname
****************************************************************************/
void SeparateFile(hDlg, lpDestPath, lpDestFileName, lpSrcFileName)
HWND hDlg;
LPSTR lpDestPath, lpDestFileName, lpSrcFileName;
{
LPSTR lpTmp;
char cTmp;
lpTmp = lpSrcFileName + (long) lstrlen(lpSrcFileName);
while (*lpTmp != ':' && *lpTmp != '\\' && lpTmp > lpSrcFileName)
lpTmp = AnsiPrev(lpSrcFileName, lpTmp);
if (*lpTmp != ':' && *lpTmp != '\\') {
lstrcpy(lpDestFileName, lpSrcFileName);
lpDestPath[0] = 0;
return;
}
lstrcpy(lpDestFileName, lpTmp + 1);
cTmp = *(lpTmp + 1);
lstrcpy(lpDestPath, lpSrcFileName);
*(lpTmp + 1) = cTmp;
lpDestPath[(lpTmp - lpSrcFileName) + 1] = 0;
}
/****************************************************************************
FUNCTION: AddExt(PSTR, PSTR);
PURPOSE: Add default extension
/***************************************************************************/
void AddExt(Name, Ext)
PSTR Name, Ext;
{
PSTR pTptr;
pTptr = Name;
while (*pTptr && *pTptr != '.')
pTptr++;
if (*pTptr != '.')
strcat(Name, Ext);
}
/****************************************************************************
FUNCTION: CheckFileName(HWND, PSTR, PSTR)
PURPOSE: Check for wildcards, add extension if needed
COMMENTS:
Make sure you have a filename and that it does not contain any
wildcards. If needed, add the default extension. This function is
called whenever your application wants to save a file.
****************************************************************************/
BOOL CheckFileName(hWnd, pDest, pSrc)
HWND hWnd;
PSTR pDest, pSrc;
{
PSTR pTmp;
if (!pSrc[0])
return (FALSE); /* Indicates no filename was specified
pTmp = pSrc;
while (*pTmp) { /* Searches the string for wildcards
switch (*pTmp++) {
case '*':
case '?':
MessageBox(hWnd, "Wildcards not allowed.",
NULL, MB_OK | MB_ICONEXCLAMATION);
return (FALSE);
}
}
AddExt(pSrc, DefExt); /* Adds the default extension if needed
if (OpenFile(pSrc, (LPOFSTRUCT) &OfStruct, OF_EXIST) >= 0) {
sprintf(str, "Replace existing %s?", pSrc);
if (MessageBox(hWnd, str, "PrntFile",
MB_OKCANCEL | MB_ICONEXCLAMATION) == IDCANCEL)
return (FALSE);
}
strcpy(pDest, pSrc);
return (TRUE);
}
/****************************************************************************
FUNCTION: SaveFile(HWND)
PURPOSE: Save current file
COMMENTS:
This saves the current contents of the Edit buffer, and changes
bChanges to indicate that the buffer has not been changed since the
last save.
Before the edit buffer is sent, you must get its handle and lock it
to get its address. Once the file is written, you must unlock the
buffer. This allows Windows to move the buffer when not in immediate
use.
****************************************************************************/
BOOL SaveFile(hWnd)
HWND hWnd;
{
BOOL bSuccess;
int IOStatus; /* result of a file write
if ((hFile = OpenFile(FileName, &OfStruct,
OF_PROMPT | OF_CANCEL | OF_CREATE)) < 0) {
/* If the file can't be saved */
sprintf(str, "Cannot write to %s.", FileName);
MessageBox(hWnd, str, NULL, MB_OK | MB_ICONHAND);
return (FALSE);
}
hEditBuffer = SendMessage(hEditWnd, EM_GETHANDLE, 0, 0L);
pEditBuffer = LocalLock(hEditBuffer);
/* Set the cursor to an hourglass during the file transfer */
hSaveCursor = SetCursor(hHourGlass);
IOStatus = write(hFile, pEditBuffer, strlen(pEditBuffer));
close(hFile);
SetCursor(hSaveCursor);
if (IOStatus != strlen(pEditBuffer)) {
sprintf(str, "Error writing to %s.", FileName);
MessageBox(hWnd, str,
NULL, MB_OK | MB_ICONHAND);
bSuccess = FALSE;
}
else {
bSuccess = TRUE; /* Indicates the file was saved
bChanges = FALSE; /* Indicates changes have been saved
}
LocalUnlock(hEditBuffer);
return (bSuccess);
}
/****************************************************************************
FUNCTION: QuerySaveFile(HWND);
PURPOSE: Called when some action might lose current contents
COMMENTS:
This function is called whenever we are about to take an action that
would lose the current contents of the edit buffer.
****************************************************************************/
BOOL QuerySaveFile(hWnd)
HWND hWnd;
{
int Response;
FARPROC lpSaveAsDlg;
if (bChanges) {
sprintf(str, "Save current changes: %s", FileName);
Response = MessageBox(hWnd, str,
"PrntFile", MB_YESNOCANCEL | MB_ICONHAND);
if (Response == IDYES) {
check_name:
/* Make sure there is a filename to save to */
if (!FileName[0]) {
lpSaveAsDlg = MakeProcInstance(SaveAsDlg, hInst);
Response = DialogBox(hInst, "SaveAs",
hWnd, lpSaveAsDlg);
FreeProcInstance(lpSaveAsDlg);
if (Response == IDOK)
goto check_name;
else
return (FALSE);
}
SaveFile(hWnd);
}
else if (Response == IDCANCEL)
return (FALSE);
}
else
return (TRUE);
}
/****************************************************************************
FUNCTION: SetNewBuffer(HWND, HANDLE, PSTR)
PURPOSE: Set new buffer for edit window
COMMENTS:
Point the edit window to the new buffer, update the window title, and
redraw the edit window. If hNewBuffer is NULL, then create an empty
1K buffer, and return its handle.
****************************************************************************/
void SetNewBuffer(hWnd, hNewBuffer, Title)
HWND hWnd;
HANDLE hNewBuffer;
PSTR Title;
{
HANDLE hOldBuffer;
hOldBuffer = SendMessage(hEditWnd, EM_GETHANDLE, 0, 0L);
LocalFree(hOldBuffer);
if (!hNewBuffer) /* Allocates a buffer if none exists
hNewBuffer = LocalAlloc(LMEM_MOVEABLE | LMEM_ZEROINIT, 1);
SendMessage(hEditWnd, EM_SETHANDLE, hNewBuffer, 0L); /* Updates the buffe
and displays new buffer */
SetWindowText(hWnd, Title);
SetFocus(hEditWnd);
bChanges = FALSE;
}
/****************************************************************************
FUNCTION: GetPrinterDC()
PURPOSE: Get hDc for current device on current output port according to
info in WIN.INI.
COMMENTS:
Searches WIN.INI for information about what printer is connected, and
if found, creates a DC for the printer.
returns
hDC > 0 if success
hDC = 0 if failure
****************************************************************************/
HANDLE GetPrinterDC()
{
char pPrintInfo[80];
LPSTR lpTemp;
LPSTR lpPrintType;
LPSTR lpPrintDriver;
LPSTR lpPrintPort;
if (!GetProfileString("windows", "Device", (LPSTR)"", pPrintInfo, 80))
return (NULL);
lpTemp = lpPrintType = pPrintInfo;
lpPrintDriver = lpPrintPort = 0;
while (*lpTemp) {
if (*lpTemp == ',') {
*lpTemp++ = 0;
while (*lpTemp == ' ')
lpTemp = AnsiNext(lpTemp);
if (!lpPrintDriver)
lpPrintDriver = lpTemp;
else {
lpPrintPort = lpTemp;
break;
}
}
else
lpTemp = AnsiNext(lpTemp);
}
return (CreateDC(lpPrintDriver, lpPrintType, lpPrintPort, (LPSTR) NULL));
}
/****************************************************************************
FUNCTION: AbortProc()
PURPOSE: Processes messages for the Abort Dialog box
****************************************************************************/
int FAR PASCAL AbortProc(hPr, Code)
HDC hPr; /* for multiple printer display contexts
int Code; /* printing status */
{
MSG msg;
/* Process messages intended for the abort dialog box */
while (!bAbort && PeekMessage(&msg, NULL, NULL, NULL, TRUE))
if (!IsDialogMessage(hAbortDlgWnd, &msg)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
/* bAbort is TRUE (return is FALSE) if the user has aborted */
return (!bAbort);
}
/****************************************************************************
FUNCTION: AbortDlg(HWND, unsigned, WORD, LONG)
PURPOSE: Processes messages for printer abort dialog box
MESSAGES:
WM_INITDIALOG - initialize dialog box
WM_COMMAND - Input received
COMMENTS
This dialog box is created while the program is printing, and allows
the user to cancel the printing process.
****************************************************************************/
int FAR PASCAL AbortDlg(hDlg, msg, wParam, lParam)
HWND hDlg;
unsigned msg;
WORD wParam;
LONG lParam;
{
switch(msg) {
/* Watch for Cancel button, RETURN key, ESCAPE key, or SPACE BAR */
case WM_COMMAND:
return (bAbort = TRUE);
case WM_INITDIALOG:
/* Set the focus to the Cancel box of the dialog */
SetFocus(GetDlgItem(hDlg, IDCANCEL));
SetDlgItemText(hDlg, IDC_FILENAME, FileName);
return (TRUE);
}
return (FALSE);
}
/****************************************************************************
FUNCTION: About(HWND, unsigned, WORD, LONG)
PURPOSE: Processes messages for "About" dialog box
MESSAGES:
WM_INITDIALOG - initialize dialog box
WM_COMMAND - Input received
****************************************************************************/
BOOL FAR PASCAL About(hDlg, message, wParam, lParam)
HWND hDlg;
unsigned message;
WORD wParam;
LONG lParam;
{
switch (message) {
case WM_INITDIALOG:
return (TRUE);
case WM_COMMAND:
if (wParam == IDOK
|| wParam == IDCANCEL) {
EndDialog(hDlg, TRUE);
return (TRUE);
}
return (TRUE);
}
return (FALSE);
}
RAINBOW.C
CD-ROM Disc Path: \SAMPCODE\WIN_SDK\RAINBOW\RAINBOW.C
/*
* RAINBOW -- Example Dialog Editor custom control
*
*/
#include <windows.h>
#include <custcntl.h>
#include "rainbow.h"
/* global static variables */
HANDLE hLibData;
HANDLE hLibInstance;
LPFNSTRTOID lpfnVerId;
LPFNIDTOSTR lpfnIdStr;
/* string for property lists */
#define IDFNLO "lpfnIdFnLo"
#define IDFNHI "lpfnIdFnHi"
#define RAINBOWCLASS "Rainbow"
/* general rainbow definitions */
#define ID GetWindowWord( hWnd, GWW_ID )
#define PARENT GetWindowWord( hWnd, GWW_HWNDPARENT )
#define INSTANCE GetWindowWord( hWnd, GWW_HINSTANCE )
/* rainbow specific definitions */
#define RAINBOW_EXTRA 12
#define RANGE GetWindowWord( hWnd, 0 )
#define TABLE GetWindowWord( hWnd, 2 )
#define WIDTH GetWindowWord( hWnd, 4 )
#define HEIGHT GetWindowWord( hWnd, 6 )
#define CHOICE GetWindowWord( hWnd, 8 )
#define CAPTURE GetWindowWord( hWnd, 10 )
#define SET_RANGE(x) SetWindowWord( hWnd, 0, x )
#define SET_TABLE(x) SetWindowWord( hWnd, 2, x )
#define SET_WIDTH(x) SetWindowWord( hWnd, 4, x )
#define SET_HEIGHT(x) SetWindowWord( hWnd, 6, x )
#define SET_CHOICE(x) SetWindowWord( hWnd, 8, x )
#define SET_CAPTURE(x) SetWindowWord( hWnd, 10, x )
/* caret related definitions */
#define CARET_XPOS ((CHOICE*WIDTH)+3)
#define CARET_YPOS (3)
#define CARET_WIDTH (WIDTH-6)
#define CARET_HEIGHT (HEIGHT-6)
/* selector related definitions */
#define SELECTOR_XPOS ((CHOICE*WIDTH)+1)
#define SELECTOR_YPOS (1)
#define SELECTOR_WIDTH (WIDTH-2)
#define SELECTOR_HEIGHT (HEIGHT-2)
/* undocumented internal function definitions */
int FAR PASCAL lstrlen( LPSTR );
int FAR PASCAL lstrcmp( LPSTR, LPSTR );
LPSTR FAR PASCAL lstrcpy( LPSTR, LPSTR );
LPSTR FAR PASCAL lstrcat( LPSTR, LPSTR );
/* internal rainbow function prototypes */
BOOL FAR PASCAL RainbowDlgFn( HWND, WORD, WORD, LONG );
LONG FAR PASCAL RainbowWndFn( HWND, WORD, WORD, LONG );
void static DrawSelector( HWND, HDC );
/*♀*/
/*
* LibMain( hInstance, wDataSegment, wHeapSize, lpszCmdLine ) : WORD
*
* hInstance library instance handle
* wDataSegment library data segment
* wHeapSize default heap size
* lpszCmdLine command line arguments
*
* LibMain is called by LibEntry, which is called by Windows when
* the DLL is loaded. The LibEntry routine is provided
* in the LIBENTRY.OBJ in the SDK Link Libraries disk. (The source
* LIBENTRY.ASM is also provided.)
*
* LibEntry initializes the DLL's heap, if a HEAPSIZE value is
* specified in the DLL's DEF file. Then LibEntry calls
* LibMain. The LibMain function below satisfies that call.
*
* LibMain performs all the initialization necessary to use the
* rainbow user control. Included in this initialization is the
* registration of the Rainbow window class.
*
*/
int FAR PASCAL LibMain(
HANDLE hInstance,
WORD wDataSegment,
WORD wHeapSize,
LPSTR lpszCmdLine )
{
HANDLE hClassStruct;
LPWNDCLASS lpClassStruct;
/* register rainbow window if necessary */
if ( hLibInstance == NULL ) {
/* allocate memory for class structure */
hClassStruct = GlobalAlloc( GHND, (DWORD)sizeof(WNDCLASS) );
if ( hClassStruct ) {
/* lock it down */
lpClassStruct = (LPWNDCLASS)GlobalLock( hClassStruct );
if ( lpClassStruct ) {
/* define class attributes */
lpClassStruct->lpszClassName = (LPSTR)RAINBOWCLASS;
lpClassStruct->hCursor = LoadCursor( NULL, IDC_ARROW );
lpClassStruct->lpszMenuName = (LPSTR)NULL;
lpClassStruct->style = CS_HREDRAW|CS_VREDRAW|CS_DBLCLKS|CS_GLO
lpClassStruct->lpfnWndProc = RainbowWndFn;
lpClassStruct->hInstance = hInstance;
lpClassStruct->hIcon = NULL;
lpClassStruct->cbWndExtra = RAINBOW_EXTRA;
lpClassStruct->hbrBackground = (HBRUSH)(COLOR_WINDOW + 1 );
/* register rainbow window class */
hLibInstance = ( RegisterClass(lpClassStruct) ) ? hInstance : NULL;
/* unlock structure */
GlobalUnlock( hClassStruct );
}
/* release class structure */
GlobalFree( hClassStruct );
}
}
/* return result 1 = success; 0 = fail */
return( hLibInstance? 1:0 );
}
/*♀*/
/****************************************************************************
FUNCTION: WEP(int)
PURPOSE: Performs cleanup tasks when the DLL is unloaded. WEP() is
called automatically by Windows when the DLL is unloaded
(no remaining tasks still have the DLL loaded). It is
strongly recommended that a DLL have a WEP() function,
even if it does nothing but return, as in this example.
*****************************************************************************
VOID FAR PASCAL WEP (bSystemExit)
int bSystemExit;
{
return;
}
/*
* RainbowInfo() : HANDLE
*
* This function returns a handle to a global block of memory that
* contains various information about the kinds of controls the library
* is capable of supporting. This data block can, for example, be used
* by the dialog editor when determining the capabilities of a particular
* control library.
*
* Note that this handle becomes the property of the caller once this
* function returns. This implies that the caller must call GlobalFree
* once it is finished with the data.
*
*/
HANDLE FAR PASCAL RainbowInfo()
{
HANDLE hCtlInfo;
LPCTLINFO lpCtlInfo;
/* allocate space for information structure */
hCtlInfo = GlobalAlloc( GHND, (DWORD)sizeof(CTLINFO) );
if ( hCtlInfo ) {
/* attempt to lock it down */
lpCtlInfo = (LPCTLINFO)GlobalLock( hCtlInfo );
if ( lpCtlInfo ) {
/* define the fixed portion of the structure */
lpCtlInfo->wVersion = 100;
lpCtlInfo->wCtlTypes = 1;
lstrcpy( lpCtlInfo->szClass, RAINBOWCLASS );
lstrcpy( lpCtlInfo->szTitle, "Sample User Control" );
/* define the variable portion of the structure */
lpCtlInfo->Type[0].wWidth = 33;
lpCtlInfo->Type[0].wHeight = 20;
lpCtlInfo->Type[0].dwStyle = WS_CHILD;
lstrcpy( lpCtlInfo->Type[0].szDescr, "Rainbow" );
/* unlock it */
GlobalUnlock( hCtlInfo );
} else {
GlobalFree( hCtlInfo );
hCtlInfo = NULL;
}
}
/* return result */
return( hCtlInfo );
}
/*♀*/
/*
* RainbowStyle( hWnd, hCtlStyle, lpfnVeriyId, lpfnGetIdStr ) : BOOL;
*
* hWnd handle to parent window
* hCtlStyle handle to control style
* lpfnVerifyId pointer to the VerifyId function from Dialog editor
* lpfnGetIdStr pointer to the GetIdStr functionn from Dialog editor
*
* This function enables the user to edit the style of a particular
* control provided. The current control style information is passed
* in using a handle to a control style data structure.
*
* This function returns this same handle (referencing updated
* information) if the dialog box is normally closed. A value of
* NULL is returned if the user cancelled the operation.
*
*/
BOOL FAR PASCAL RainbowStyle(
HWND hWnd,
HANDLE hCtlStyle,
LPFNSTRTOID lpfnVerifyId,
LPFNIDTOSTR lpfnGetIdStr )
{
FARPROC lpDlgFn;
HANDLE hNewCtlStyle;
/* initialization */
hLibData = hCtlStyle;
lpfnVerId = lpfnVerifyId;
lpfnIdStr = lpfnGetIdStr;
/* display dialog box */
lpDlgFn = MakeProcInstance( (FARPROC)RainbowDlgFn, hLibInstance );
hNewCtlStyle = ( DialogBox(hLibInstance,"RainbowStyle",hWnd,lpDlgFn) ) ? hL
FreeProcInstance( lpDlgFn );
/* return updated data block */
return( hNewCtlStyle );
}
/*♀*/
/*
* RainbowFlags( wFlags, lpszString, wMaxString ) : WORD;
*
* wFlags class style flags
* lpszString class style string
* wMaxString maximum size of class style string
*
* This function translates the class style flags provided into a
* corresponding text string for output to an RC file. The general
* windows flags (contained in the low byte) are not interpreted,
* only those in the high byte.
*
* The value returned by this function is the library instance
* handle when sucessful, and NULL otherwise.
*
*/
WORD FAR PASCAL RainbowFlags(
WORD wFlags,
LPSTR lpszString,
WORD wMaxString )
{
lpszString[0] = NULL;
return( 0 );
}
/*♀*/
/*
* RainbowWndFn( hWnd, wMsg, wParam, lParam ) : LONG
*
* hWnd handle to rainbow window
* wMsg message number
* wParam single word parameter
* lParam double word parameter
*
* This function is responsible for processing all the messages
* which relate to the rainbow control window. Note how the
* code is written to avoid potential problems when re-entrancy
* ocurrs - this involves the use of extra bytes associated with
* the window data structure.
*
* The LONG value returned by this function is either a value
* returned by the internal handling of the message or by the
* default window procedure.
*
*/
LONG FAR PASCAL RainbowWndFn( hWnd, wMsg, wParam, lParam )
HWND hWnd;
WORD wMsg;
WORD wParam;
LONG lParam;
{
/* local variables */
LONG lResult; /* temporary result variable */
/* initialization */
lResult = TRUE;
/* process message */
switch( wMsg )
{
case WM_GETDLGCODE : /* capture all key strokes */
lParam = DLGC_WANTARROWS;
break;
case WM_CREATE : /* create pallette window */
{
/* temporary variables */
HANDLE hrgbList; /* handle to rgb list */
LONG FAR * lprgbEntry; /* pointer to rgb list */
/* allocate space for rgb color list */
hrgbList = GlobalAlloc( GMEM_MOVEABLE, sizeof(LONG)*16L );
if ( hrgbList ) {
/*
* Define initial rgb color & value list - note that
* eight default colors are selected with the values
* matching each of the colors.
*/
lprgbEntry = (LONG FAR *)GlobalLock( hrgbList );
lprgbEntry[0] = RGB( 0x00, 0x00, 0x00 );
lprgbEntry[1] = RGB( 0x00, 0x00, 0xFF );
lprgbEntry[2] = RGB( 0x00, 0xFF, 0x00 );
lprgbEntry[3] = RGB( 0xFF, 0x00, 0x00 );
lprgbEntry[4] = RGB( 0x00, 0xFF, 0xFF );
lprgbEntry[5] = RGB( 0xFF, 0xFF, 0x00 );
lprgbEntry[6] = RGB( 0xFF, 0x00, 0xFF );
lprgbEntry[7] = RGB( 0xFF, 0xFF, 0xFF );
lprgbEntry[8] = RGB( 0x00, 0x00, 0x00 );
lprgbEntry[9] = RGB( 0x00, 0x00, 0xFF );
lprgbEntry[10] = RGB( 0x00, 0xFF, 0x00 );
lprgbEntry[11] = RGB( 0xFF, 0x00, 0x00 );
lprgbEntry[12] = RGB( 0x00, 0xFF, 0xFF );
lprgbEntry[13] = RGB( 0xFF, 0xFF, 0x00 );
lprgbEntry[14] = RGB( 0xFF, 0x00, 0xFF );
lprgbEntry[15] = RGB( 0xFF, 0xFF, 0xFF );
GlobalUnlock( hrgbList );
/* define instance variables */
SET_RANGE( 8 );
SET_TABLE( hrgbList );
SET_WIDTH( ((LPCREATESTRUCT)lParam)->cx / 8 );
SET_HEIGHT( ((LPCREATESTRUCT)lParam)->cy );
SET_CHOICE( 0 );
SET_CAPTURE( FALSE );
} else
DestroyWindow( hWnd );
}
break;
case WM_SIZE : /* window being resized */
/* redefine width & height instance variables */
SET_WIDTH( LOWORD(lParam) / 8 );
SET_HEIGHT( HIWORD(lParam) );
break;
case WM_PAINT : /* paint control window */
{
PAINTSTRUCT Ps; /* paint structure */
WORD wEntry; /* current color entry */
HANDLE hBrush; /* handle to new brush */
HANDLE hOldBrush; /* handle to old brush */
LONG FAR * lprgbEntry; /* pointer to rgb list */
/* start paint operation */
BeginPaint( hWnd, (LPPAINTSTRUCT)&Ps );
/* iteratively paint each color patch */
lprgbEntry = (LONG FAR *)GlobalLock( TABLE );
for ( wEntry=0; wEntry<RANGE; wEntry++ ) {
/* create solid brush for patch & select */
hBrush = CreateSolidBrush( lprgbEntry[wEntry] );
hOldBrush = SelectObject( Ps.hdc, hBrush );
/* draw rectangle with brush fill */
Rectangle(
Ps.hdc,
wEntry*WIDTH,
0,
(wEntry*WIDTH)+WIDTH,
HEIGHT
);
/* unselect brush and delete */
SelectObject( Ps.hdc, hOldBrush );
DeleteObject( hBrush );
}
GlobalUnlock( TABLE );
/* End paint operation */
EndPaint( hWnd, (LPPAINTSTRUCT)&Ps );
}
break;
case WM_KEYDOWN : /* key being pressed */
{
/* local variables */
HDC hDC; /* display context handle */
LONG FAR * lprgbEntry; /* pointer to rgb list */
/* retrieve display context & unmark current selection */
hDC = GetDC( hWnd );
DrawSelector( hWnd, hDC );
/* process virtual key codes */
switch( wParam )
{
case VK_HOME : /* home key */
SET_CHOICE( 0 );
break;
case VK_UP : /* up cursor key */
case VK_LEFT : /* left cursor key */
SET_CHOICE( (CHOICE > 0) ? CHOICE-1 : RANGE-1 );
break;
case VK_DOWN : /* down cursor key */
case VK_RIGHT : /* right cursor key */
case VK_SPACE : /* space bar - move right */
SET_CHOICE( (CHOICE < RANGE-1) ? CHOICE+1 : 0 );
break;
case VK_END : /* end key */
SET_CHOICE( RANGE-1 );
break;
default : /* some other key */
lResult = FALSE;
break;
}
/* mark new selection & release display context */
DrawSelector( hWnd, hDC );
ReleaseDC( hWnd, hDC );
/* move caret to new position */
SetCaretPos( CARET_XPOS, CARET_YPOS );
/* notify parent of new selection */
lprgbEntry = (LONG FAR *)GlobalLock( TABLE );
SendMessage(PARENT,WM_COMMAND,ID,lprgbEntry[RANGE+CHOICE]);
GlobalUnlock( TABLE );
}
break;
case WM_SETFOCUS : /* get focus - display caret */
/* create caret & display */
CreateCaret( hWnd, NULL, CARET_WIDTH, CARET_HEIGHT );
SetCaretPos( CARET_XPOS, CARET_YPOS );
ShowCaret( hWnd );
break;
case WM_LBUTTONDOWN : /* left button depressed - fall through */
{
/* local variables */
HDC hDC; /* display context handle */
LONG FAR * lprgbEntry; /* pointer to rgb list */
/* retrieve display context */
hDC = GetDC ( hWnd );
/* unmark old selection & mark new one */
DrawSelector( hWnd, hDC );
SET_CHOICE( LOWORD(lParam)/WIDTH );
DrawSelector( hWnd, hDC );
/* release display context & move caret */
ReleaseDC( hWnd, hDC );
/* capture focus & move caret */
SetFocus(hWnd);
SetCaretPos( CARET_XPOS, CARET_YPOS );
/* notify parent of new selection */
lprgbEntry = (LONG FAR *)GlobalLock( TABLE );
SendMessage(PARENT,WM_COMMAND,ID,lprgbEntry[RANGE+CHOICE]);
GlobalUnlock( TABLE );
/* activate capture */
SetCapture( hWnd );
SET_CAPTURE( TRUE );
}
break;
case WM_MOUSEMOVE : /* mouse being moved */
/* track mouse only if capture on */
if ( CAPTURE ) {
/* local variables */
HDC hDC; /* display context handle */
WORD wNewChoice; /* new mouse selection */
LONG FAR * lprgbEntry; /* pointer to rgb list */
/* calculate new selection */
wNewChoice = ( LOWORD(lParam) <= 0 ) ?
0 :
( LOWORD(lParam)/WIDTH >= RANGE ) ?
RANGE - 1 :
LOWORD(lParam) / WIDTH;
/* update display if different */
if ( wNewChoice != CHOICE ) {
/* retrieve display context */
hDC = GetDC ( hWnd );
/* unmark old selection & mark new one */
DrawSelector( hWnd, hDC );
SET_CHOICE( wNewChoice );
DrawSelector( hWnd, hDC );
/* release display context & move caret */
ReleaseDC( hWnd, hDC );
SetCaretPos( CARET_XPOS, CARET_YPOS );
/* notify parent of new selection */
lprgbEntry = (LONG FAR *)GlobalLock( TABLE );
SendMessage(PARENT,WM_COMMAND,ID,lprgbEntry[RANGE+CHOICE]);
GlobalUnlock( TABLE );
}
}
break;
case WM_LBUTTONUP : /* left button released */
/* release capture if active */
if ( CAPTURE ) {
SET_CAPTURE( FALSE );
ReleaseCapture();
}
break;
case WM_KILLFOCUS : /* kill focus - hide caret */
DestroyCaret();
break;
case RM_SETSEL : /* select a color entry */
{
LONG FAR * lprgbEntry;
/* update selection & redraw rainbow */
SET_CHOICE( (wParam >= RANGE) ? 0 : wParam );
InvalidateRect( hWnd, NULL, TRUE );
/* notify parent of change in color */
lprgbEntry = (LONG FAR *)GlobalLock( TABLE );
SendMessage( PARENT, WM_COMMAND, ID, lprgbEntry[RANGE+CHOICE] );
GlobalUnlock( TABLE );
/* return new choice */
lResult = CHOICE;
}
break;
case RM_GETSEL : /* retrieve selected color */
{
LONG FAR * lprgbEntry;
/* return selected entry */
lResult = CHOICE;
/* define selected color */
lprgbEntry = (LONG FAR *)GlobalLock( TABLE );
*(LONG FAR *)lParam = lprgbEntry[RANGE+CHOICE];
GlobalUnlock( TABLE );
}
break;
case RM_SETCOLORS : /* define rainbow color table */
{
WORD wEntry;
HANDLE hrgbList;
RECT rectClient;
LONG FAR * lprgbEntry;
/* release previous table from memory */
GlobalFree( TABLE );
hrgbList = GlobalAlloc( GMEM_MOVEABLE, sizeof(LONG)*wParam*2L);
if ( hrgbList ) {
/* define initial rgb colors & values */
lprgbEntry = (LONG FAR *)GlobalLock( hrgbList );
for ( wEntry=0; wEntry < wParam; wEntry++ ) {
lprgbEntry[wEntry] = ((LONG FAR*)lParam)[wEntry];
lprgbEntry[wParam+wEntry] = ((LONG FAR*)lParam)[wParam+wEntry];
}
GlobalUnlock( hrgbList );
/* retrieve current window dimensions */
GetClientRect( hWnd, &rectClient );
/* re-define instance variables */
SET_RANGE( wParam );
SET_TABLE( hrgbList );
SET_WIDTH( (rectClient.right-rectClient.left)/wParam );
SET_HEIGHT( rectClient.bottom-rectClient.top );
SET_CHOICE( 0 );
/* update window & notify parent of new selection */
InvalidateRect( hWnd, NULL, TRUE );
SendMessage( PARENT, WM_COMMAND, ID, lprgbEntry[RANGE+CHOICE] );
/* normal return */
lResult = wParam;
} else
lResult = -1L;
}
break;
case RM_GETCOLORS : /* retrieve rainbow color table */
{
WORD wEntry;
LONG FAR * lprgbEntry;
/* retrieve number of colors */
lResult = RANGE;
/* retrieve rgb color list */
lprgbEntry = (LONG FAR *)GlobalLock( TABLE );
for ( wEntry=0; (wEntry < RANGE)&&(wEntry < wParam); wEntry++ ) {
((LONG FAR *)lParam)[wEntry] = lprgbEntry[wEntry];
((LONG FAR *)lParam)[RANGE+wEntry] = lprgbEntry[RANGE+wEntry];
}
GlobalUnlock( TABLE );
}
break;
case WM_DESTROY : /* window being destroyed */
GlobalFree( TABLE );
break;
default : /* default window message processing */
lResult = DefWindowProc( hWnd, wMsg, wParam, lParam );
break;
}
/* return final result */
return( lResult );
}
/*♀*/
/*
* RainbowDlgFn( hDlg, wMessage, wParam, lParam ) : BOOL;
*
* hDlg dialog box handle
* wMessage current window message
* wParam word parameter
* lParam long parameter
*
* This function is responsible for processing all the messages that
* relate to the style dialog box. This function transfers data
* between itself and the RainbowStyle using a global data handle.
*
* If the user presses the OK button, this data handle is used to pass
* back a new style data block. It is left to the calling routine to
* delete this new block.
*
*/
BOOL FAR PASCAL RainbowDlgFn(
HWND hDlg,
WORD wMessage,
WORD wParam,
LONG lParam )
{
BOOL bResult;
/* initialization */
bResult = TRUE;
/* process message */
switch( wMessage )
{
case WM_INITDIALOG :
{
HANDLE hCtlStyle;
LPCTLSTYLE lpCtlStyle;
char szId[ 20 ]; /* temp. string to hold id */
/* disable Ok button & save dialog data handle */
hCtlStyle = hLibData;
EnableWindow( GetDlgItem(hDlg,IDOK), FALSE );
/* retrieve & display style parameters */
if ( hCtlStyle ) {
/* add handle to property list */
SetProp( hDlg, MAKEINTRESOURCE(1), hCtlStyle );
/* update dialog box fields */
lpCtlStyle = (LPCTLSTYLE)GlobalLock( hCtlStyle );
SetDlgItemText( hDlg, IDTEXT, lpCtlStyle->szTitle );
/* Kanhom Ng 2/7/89
* Set the id value string correctly.
* Save the pointer to the verify id function from dialog editor
*/
if ( lpfnIdStr )
{
(*lpfnIdStr)(lpCtlStyle->wId, (LPSTR)szId, sizeof( szId ) );
SetDlgItemText( hDlg, IDVALUE, szId );
}
else
{
EnableWindow( GetDlgItem( hDlg, IDVALUE ), FALSE );
}
lstrcpy( lpCtlStyle->szClass, RAINBOWCLASS );
SetProp( hDlg, IDFNHI, HIWORD( (DWORD)lpfnVerId ) );
SetProp( hDlg, IDFNLO, LOWORD( (DWORD)lpfnVerId ) );
GlobalUnlock( hCtlStyle );
} else
EndDialog( hDlg, FALSE );
}
break;
case WM_COMMAND :
/* process sub-message */
switch( wParam )
{
case IDCANCEL : /* cancel dialog box */
RemoveProp( hDlg, MAKEINTRESOURCE(1) );
RemoveProp( hDlg, IDFNLO );
RemoveProp( hDlg, IDFNHI );
EndDialog( hDlg, FALSE );
break;
case IDOK : /* save dialog changes */
{
HANDLE hCtlStyle;
LPCTLSTYLE lpCtlStyle;
LPFNSTRTOID lpfnId; /* pointer to the verify id function from
char szId[ 20 ]; /* temp. string to hold the id */
hCtlStyle = GetProp( hDlg, MAKEINTRESOURCE(1) );
/* update structure contents */
lpCtlStyle = (LPCTLSTYLE)GlobalLock( hCtlStyle );
szId[ 0 ] = NULL;
GetDlgItemText( hDlg, IDVALUE, szId, sizeof(szId) );
lpfnId = (LPFNSTRTOID)MAKELONG( GetProp( hDlg, IDFNLO ), GetProp( hDl
if ( lpfnId )
{
DWORD dwResult; /* result ofthe verifyId function */
dwResult = (*lpfnId)( (LPSTR)szId );
if ( !(BOOL)dwResult )
{
/* Wrong id */
GlobalUnlock( hCtlStyle );
break;
}
lpCtlStyle->wId = HIWORD( dwResult );
}
GetDlgItemText( hDlg, IDTEXT, lpCtlStyle->szTitle, sizeof(lpCtlStyle-
GlobalUnlock( hCtlStyle );
RemoveProp( hDlg, MAKEINTRESOURCE(1) );
RemoveProp( hDlg, IDFNLO );
RemoveProp( hDlg, IDFNHI );
/* end dialog box */
hLibData = hCtlStyle;
EndDialog( hDlg, TRUE );
}
break;
case IDTEXT : /* control text */
case IDVALUE : /* control id */
/* enable or disable Ok button */
if ( HIWORD(lParam) == EN_CHANGE )
EnableWindow(
GetDlgItem(hDlg,IDOK),
(SendMessage(GetDlgItem(hDlg,IDTEXT),WM_GETTEXTLENGTH,0,0L) &&
SendMessage(GetDlgItem(hDlg,IDVALUE),WM_GETTEXTLENGTH,0,0L)) ? TRU
);
break;
default : /* something else */
bResult = FALSE;
break;
}
break;
default :
bResult = FALSE;
break;
}
/* return final result */
return( bResult );
}
/*♀*/
/*
* DrawSelector( hWnd, hDC ) : void;
*
* hWnd window handle
* hDC handle to display context
*
* This function is responsible for drawing the selector
* which surrounds the active color patch. This drawing
* process involves the use of the R2_NOT operator to
* simplify the drawing & re-drawing process.
*
*/
void static DrawSelector( hWnd, hDC )
HWND hWnd;
HDC hDC;
{
/* local variables */
HANDLE hOldPen; /* old pen */
WORD wOldROP2; /* old raster op code */
WORD wOldBkMode; /* old background mode */
/* setup display context */
wOldROP2 = SetROP2( hDC, R2_NOT );
wOldBkMode = SetBkMode( hDC, TRANSPARENT );
hOldPen = SelectObject( hDC, CreatePen(0,1,RGB(0,0,0)) );
/* draw selector rectangle */
Rectangle(
hDC,
SELECTOR_XPOS,
SELECTOR_YPOS,
SELECTOR_XPOS+SELECTOR_WIDTH,
SELECTOR_YPOS+SELECTOR_HEIGHT
);
DeleteObject( SelectObject(hDC,hOldPen) );
/* restore display context */
SetBkMode( hDC, wOldBkMode );
SetROP2( hDC, wOldROP2 );
}
SELECT.C
CD-ROM Disc Path: \SAMPCODE\WIN_SDK\SELECT\SELECT.C
/****************************************************************************
PROGRAM: Select.c
PURPOSE: Contains library routines for selecting a region
FUNCTIONS:
StartSelection(HWND, POINT, LPRECT, int) - begin selection area
UpdateSelection(HWND, POINT, LPRECT, int) - update selection area
EndSelection(POINT, LPRECT) - end selection area
ClearSelection(HWND, LPRECT, int) - clear selection area
*****************************************************************************
#include "windows.h"
#include "select.h"
/****************************************************************************
FUNCTION: LibMain(HANDLE, WORD, WORD, LPSTR)
PURPOSE: Is called by LibEntry. LibEntry is called by Windows when
the DLL is loaded. The LibEntry routine is provided in
the LIBENTRY.OBJ in the SDK Link Libraries disk. (The
source LIBENTRY.ASM is also provided.)
LibEntry initializes the DLL's heap, if a HEAPSIZE value is
specified in the DLL's DEF file. Then LibEntry calls
LibMain. The LibMain function below satisfies that call.
The LibMain function should perform additional initialization
tasks required by the DLL. In this example, no initialization
tasks are required. LibMain should return a value of 1 if
the initialization is successful.
*****************************************************************************
int FAR PASCAL LibMain(hModule, wDataSeg, cbHeapSize, lpszCmdLine)
HANDLE hModule;
WORD wDataSeg;
WORD cbHeapSize;
LPSTR lpszCmdLine;
{
return 1;
}
/****************************************************************************
FUNCTION: WEP(int)
PURPOSE: Performs cleanup tasks when the DLL is unloaded. WEP() is
called automatically by Windows when the DLL is unloaded (no
remaining tasks still have the DLL loaded). It is strongly
recommended that a DLL have a WEP() function, even if it does
nothing but returns success (1), as in this example.
*****************************************************************************
int FAR PASCAL WEP (bSystemExit)
int bSystemExit;
{
return(1);
}
/****************************************************************************
FUNCTION: StartSelection(HWND, POINT, LPRECT, int)
PURPOSE: Begin selection of region
****************************************************************************/
int FAR PASCAL StartSelection(hWnd, ptCurrent, lpSelectRect, fFlags)
HWND hWnd;
POINT ptCurrent;
LPRECT lpSelectRect;
int fFlags;
{
if (lpSelectRect->left != lpSelectRect->right ||
lpSelectRect->top != lpSelectRect->bottom)
ClearSelection(hWnd, lpSelectRect, fFlags);
lpSelectRect->right = ptCurrent.x;
lpSelectRect->bottom = ptCurrent.y;
/* If you are extending the box, then invert the current rectangle */
if ((fFlags & SL_SPECIAL) == SL_EXTEND)
ClearSelection(hWnd, lpSelectRect, fFlags);
/* Otherwise, set origin to current location */
else {
lpSelectRect->left = ptCurrent.x;
lpSelectRect->top = ptCurrent.y;
}
SetCapture(hWnd);
}
/****************************************************************************
FUNCTION: UpdateSelection(HWND, POINT, LPRECT, int) - update selection ar
PURPOSE: Update selection
****************************************************************************/
int FAR PASCAL UpdateSelection(hWnd, ptCurrent, lpSelectRect, fFlags)
HWND hWnd;
POINT ptCurrent;
LPRECT lpSelectRect;
int fFlags;
{
HDC hDC;
short OldROP;
hDC = GetDC(hWnd);
switch (fFlags & SL_TYPE) {
case SL_BOX:
OldROP = SetROP2(hDC, R2_NOTXORPEN);
MoveTo(hDC, lpSelectRect->left, lpSelectRect->top);
LineTo(hDC, lpSelectRect->right, lpSelectRect->top);
LineTo(hDC, lpSelectRect->right, lpSelectRect->bottom);
LineTo(hDC, lpSelectRect->left, lpSelectRect->bottom);
LineTo(hDC, lpSelectRect->left, lpSelectRect->top);
LineTo(hDC, ptCurrent.x, lpSelectRect->top);
LineTo(hDC, ptCurrent.x, ptCurrent.y);
LineTo(hDC, lpSelectRect->left, ptCurrent.y);
LineTo(hDC, lpSelectRect->left, lpSelectRect->top);
SetROP2(hDC, OldROP);
break;
case SL_BLOCK:
PatBlt(hDC,
lpSelectRect->left,
lpSelectRect->bottom,
lpSelectRect->right - lpSelectRect->left,
ptCurrent.y - lpSelectRect->bottom,
DSTINVERT);
PatBlt(hDC,
lpSelectRect->right,
lpSelectRect->top,
ptCurrent.x - lpSelectRect->right,
ptCurrent.y - lpSelectRect->top,
DSTINVERT);
break;
}
lpSelectRect->right = ptCurrent.x;
lpSelectRect->bottom = ptCurrent.y;
ReleaseDC(hWnd, hDC);
}
/****************************************************************************
FUNCTION: EndSelection(POINT, LPRECT)
PURPOSE: End selection of region, release capture of mouse movement
****************************************************************************/
int FAR PASCAL EndSelection(ptCurrent, lpSelectRect)
POINT ptCurrent;
LPRECT lpSelectRect;
{
lpSelectRect->right = ptCurrent.x;
lpSelectRect->bottom = ptCurrent.y;
ReleaseCapture();
}
/****************************************************************************
FUNCTION: ClearSelection(HWND, LPRECT, int) - clear selection area
PURPOSE: Clear the current selection
****************************************************************************/
int FAR PASCAL ClearSelection(hWnd, lpSelectRect, fFlags)
HWND hWnd;
LPRECT lpSelectRect;
int fFlags;
{
HDC hDC;
short OldROP;
hDC = GetDC(hWnd);
switch (fFlags & SL_TYPE) {
case SL_BOX:
OldROP = SetROP2(hDC, R2_NOTXORPEN);
MoveTo(hDC, lpSelectRect->left, lpSelectRect->top);
LineTo(hDC, lpSelectRect->right, lpSelectRect->top);
LineTo(hDC, lpSelectRect->right, lpSelectRect->bottom);
LineTo(hDC, lpSelectRect->left, lpSelectRect->bottom);
LineTo(hDC, lpSelectRect->left, lpSelectRect->top);
SetROP2(hDC, OldROP);
break;
case SL_BLOCK:
PatBlt(hDC,
lpSelectRect->left,
lpSelectRect->top,
lpSelectRect->right - lpSelectRect->left,
lpSelectRect->bottom - lpSelectRect->top,
DSTINVERT);
break;
}
ReleaseDC(hWnd, hDC);
}
SERVDATA.C
CD-ROM Disc Path: \SAMPCODE\WIN_SDK\DDE\SERVDATA.C
/****************************************************************************
MODULE: SERVDATA.C
PURPOSE: Maintains conversation information.
****************************************************************************/
#include "windows.h"
#include "dde.h"
#include "server.h"
#include <string.h>
typedef struct CONV
{
HWND hwndServerDDE;
HWND hwndClientDDE;
BOOL bInClientRequestedTerminate;
};
typedef struct ADVISE
{
HWND hwndServerDDE;
HWND hwndClientDDE;
int nItem;
ATOM atomItem;
BOOL bAckRequest;
BOOL bDeferUpdate;
BOOL bAwaitingAck;
HANDLE hData;
};
struct CONV Conv[CONV_MAX_COUNT];
static int nConvCount = 0;
static struct ADVISE Advise[ADVISE_MAX_COUNT];
static int nAdviseCount = 0;
struct ADVISE * NEAR FindAdvise(HWND, int);
struct CONV * NEAR FindConv(HWND);
/****************************************************************************
FUNCTION: AddAdvise
PURPOSE: Register a new hot or warm link to a specified client, for
a specified server application item (1, 2, or 3).
****************************************************************************/
BOOL AddAdvise(hwndServerDDE, hDDEAdviseOptions, atomItem, nItem)
HWND hwndServerDDE;
HANDLE hDDEAdviseOptions;
ATOM atomItem;
int nItem;
{
struct ADVISE * pAdvise;
DDEADVISE FAR * lpDDEAdviseOptions;
int nAdviseIndex;
if (nAdviseCount >= ADVISE_MAX_COUNT)
{
MessageBox(hwndMain,
"Maximum advisories exceeded",
"Server",
MB_ICONEXCLAMATION | MB_OK);
return (FALSE);
}
if ((lpDDEAdviseOptions
= (DDEADVISE FAR *)GlobalLock(hDDEAdviseOptions)) == NULL)
return (FALSE);
for (pAdvise = Advise, nAdviseIndex = 0;
nAdviseIndex < nAdviseCount;
pAdvise++, nAdviseIndex++)
{
if (pAdvise->hwndServerDDE == hwndServerDDE
&& pAdvise->nItem == nItem)
{
MessageBox(hwndMain,
"Advisory (paste link) already established",
"Server",
MB_ICONEXCLAMATION | MB_OK);
GlobalUnlock(hDDEAdviseOptions);
return (FALSE);
}
}
pAdvise = Advise + nAdviseCount++;
pAdvise->hwndServerDDE = hwndServerDDE;
pAdvise->hwndClientDDE = GetHwndClientDDE(hwndServerDDE);
pAdvise->nItem = nItem;
pAdvise->atomItem = atomItem;
pAdvise->bAckRequest = lpDDEAdviseOptions->fAckReq;
pAdvise->bDeferUpdate = lpDDEAdviseOptions->fDeferUpd;
pAdvise->bAwaitingAck = FALSE;
GlobalUnlock(hDDEAdviseOptions);
return (TRUE);
}
/****************************************************************************
FUNCTION: AddConv
PURPOSE: Register a new conversation with a client window
****************************************************************************/
BOOL AddConv(hwndServerDDE, hwndClientDDE)
HWND hwndServerDDE;
HWND hwndClientDDE;
{
struct CONV * pConv;
if (nConvCount >= CONV_MAX_COUNT)
{
return (FALSE);
}
if (FindConv(hwndServerDDE) != NULL)
{
return (FALSE); /* conversation already added */
}
pConv = Conv + nConvCount++;
pConv->hwndServerDDE = hwndServerDDE;
pConv->hwndClientDDE = hwndClientDDE;
pConv->bInClientRequestedTerminate = FALSE;
return (TRUE);
}
/***********************************************************************
FUNCTION: AtLeastOneConvActive
PURPOSE: Used during termination of application, to
determine whether any conversations are still active
while the conversations are being terminated.
***********************************************************************/
BOOL AtLeastOneConvActive()
{
return (nConvCount? TRUE: FALSE);
}
/****************************************************************************
FUNCTION: CheckOutSentData
PURPOSE: Set Awaiting Ack state to true for specified item.
****************************************************************************/
void CheckOutSentData(hwndServerDDE, nItem, atomItem, hData)
HWND hwndServerDDE;
int nItem;
ATOM atomItem;
HANDLE hData;
{
struct ADVISE * pAdvise;
if (!(pAdvise = FindAdvise(hwndServerDDE, nItem)))
return;
pAdvise->bAwaitingAck = TRUE;
pAdvise->atomItem = atomItem;
pAdvise->hData = hData;
return;
}
/****************************************************************************
FUNCTION: DoEditCopy
PURPOSE: Copy selected data to clipboard in two formats:
CF_TEXT and (registered) "Link" format.
****************************************************************************/
void DoEditCopy(nItem)
int nItem;
{
/* Format string and set clipboard data here */
HANDLE hTextData;
HANDLE hConvData;
char szItemValue[ITEM_VALUE_MAX_SIZE+1];
LPSTR lpTextData, lpConvData;
if (!GetDlgItemText(hwndMain, nItem, szItemValue, ITEM_VALUE_MAX_SIZE))
strcpy(szItemValue, " ");
/* Copy item value in CF_TEXT format to global memory object */
if (!(hTextData
= GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, (DWORD)lstrlen(szItemValue)+1))
return;
if (!(lpTextData = GlobalLock(hTextData)))
{
GlobalFree(hTextData);
return;
}
lstrcpy(lpTextData, szItemValue);
GlobalUnlock(hTextData);
/* Copy item value in "Link" format to global memory object */
if (!(hConvData
= GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE,
(DWORD)APP_MAX_SIZE+TOPIC_MAX_SIZE+ITEM_NAME_MAX_SIZE+4)))
return;
if (!(lpConvData = GlobalLock(hConvData)))
{
GlobalFree(hConvData);
return;
}
/* Compose paste link string, each sub-string is null terminated */
/* Format is <app> <null> <topic> <null> <item> <null> <null> */
lstrcpy(lpConvData, "Server");
lpConvData = lpConvData + lstrlen(lpConvData) + 1; /* '+1' adds null */
lstrcpy(lpConvData, szDocName); /* topic */
lpConvData += (lstrlen(lpConvData) + 1);
lstrcpy(lpConvData, "item#");
lpConvData[4] = '1' + nItem - 1;
*(lpConvData + lstrlen(lpConvData) + 1) = 0; /* final null */
GlobalUnlock(hConvData);
if (OpenClipboard(hwndMain))
{
EmptyClipboard();
SetClipboardData(CF_TEXT, hTextData);
SetClipboardData(cfLink, hConvData);
CloseClipboard();
}
else
{
GlobalFree(hTextData);
GlobalFree(hConvData);
}
return;
}
/****************************************************************************
FUNCTION: FindAdvise
PURPOSE: Find advisory data for a specific conversation item.
****************************************************************************/
struct ADVISE * NEAR FindAdvise(hwndServerDDE, nItem)
HWND hwndServerDDE;
int nItem;
{
struct ADVISE * pAdvise;
int nAdviseIndex;
for (nAdviseIndex = 0, pAdvise = Advise;
nAdviseIndex < nAdviseCount;
nAdviseIndex++, pAdvise++)
{
if (pAdvise->hwndServerDDE == hwndServerDDE
&& pAdvise->nItem == nItem)
{
return (pAdvise);
}
}
return (NULL);
}
/****************************************************************************
FUNCTION: FindConv
PURPOSE: Find the conversation for a specified server DDE window.
****************************************************************************/
struct CONV * NEAR FindConv(hwndServerDDE)
HWND hwndServerDDE;
{
struct CONV * pConv;
int nConvIndex;
for (nConvIndex = 0, pConv = Conv;
nConvIndex < nConvCount;
nConvIndex++, pConv++)
{
if (pConv->hwndServerDDE == hwndServerDDE)
return (pConv);
}
return (NULL);
}
/****************************************************************************
FUNCTION: GetAdviseData
PURPOSE: Get advisory data for a specified conversation item.
****************************************************************************/
BOOL GetAdviseData(hwndServerDDE, nItem, szItemName, szItemValue,
pbDeferUpdate, pbAckRequest)
HWND hwndServerDDE;
int nItem;
char * szItemName;
char * szItemValue;
BOOL * pbDeferUpdate;
BOOL * pbAckRequest;
{
struct ADVISE * pAdvise;
if (!(pAdvise = FindAdvise(hwndServerDDE, nItem)))
return (FALSE);
strcpy(szItemName, "Item#");
szItemName[4] = pAdvise->nItem==1? '1': pAdvise->nItem==2? '2': '3';
*pbDeferUpdate = pAdvise->bDeferUpdate;
*pbAckRequest = pAdvise->bAckRequest;
if (!GetDlgItemText(hwndMain, nItem, szItemValue, ITEM_VALUE_MAX_SIZE))
strcpy(szItemValue," ");
return (TRUE);
}
/****************************************************************************
FUNCTION: GetHwndClientDDE
PURPOSE: Get the hwnd of the client in conversation with a specified
server DDE window.
****************************************************************************/
HWND GetHwndClientDDE(hwndServerDDE)
HWND hwndServerDDE;
{
struct CONV * pConv;
if (!(pConv = FindConv(hwndServerDDE)))
return (NULL);
return (pConv->hwndClientDDE);
}
/****************************************************************************
FUNCTION: GetNextAdvise
PURPOSE: Find a client that needs to be notified that a value of
a specified item (a hot or warm link item) has changed.
Since a hot or warm link to the item may have been established
for multiple conversations (multiple clients), this function
is set up to step through the list of such conversations.
Start the list by passing a NULL hwndClientDDE. To get the
next conversation in the list, pass the previous client returned
by this function.
****************************************************************************/
HWND GetNextAdvise(hwndServerDDE, nItem)
HWND hwndServerDDE;
int nItem;
{
struct ADVISE * pAdvise;
int nAdviseIndex;
if (hwndServerDDE)
{
for (nAdviseIndex = 0, pAdvise = Advise;
nAdviseIndex < nAdviseCount;
nAdviseIndex++, pAdvise++)
{
if (pAdvise->hwndServerDDE == hwndServerDDE
&& pAdvise->nItem == nItem)
{
pAdvise++;
break;
}
}
if (nAdviseIndex >= nAdviseCount)
return (NULL);
}
else
{
pAdvise = Advise;
nAdviseIndex = 0;
}
for ( ; nAdviseIndex < nAdviseCount; nAdviseIndex++, pAdvise++)
{
if (pAdvise->nItem == nItem)
{
return (pAdvise->hwndServerDDE);
}
}
return (NULL);
}
/****************************************************************************
FUNCTION: GetNextConv
PURPOSE: Get next client in list of conversations. To get the
first hwndServerDDE in the conversation list, pass in a NULL
value for hwndServerDDE.
****************************************************************************/
HWND GetNextConv(hwndServerDDE)
HWND hwndServerDDE;
{
struct CONV * pConv;
int nConvIndex;
if (hwndServerDDE)
{
for (nConvIndex = 0, pConv = Conv;
nConvIndex < nConvCount;
nConvIndex++, pConv++)
{
if (pConv->hwndServerDDE == hwndServerDDE)
{
if (++nConvIndex < nConvCount)
return (++pConv)->hwndServerDDE;
else
return (NULL);
}
}
return (NULL);
}
if (nConvCount > 0)
return (Conv[0].hwndServerDDE);
else
return (NULL);
}
/****************************************************************************
FUNCTION: GlobalFreeSentData
PURPOSE: A global memory object (hData) was sent in a WM_DDE_DATA
message, but the client never used it. So, the server is
responsible for freeing the object.
****************************************************************************/
void GlobalFreeSentData(hwndServerDDE, nItem)
HWND hwndServerDDE;
int nItem;
{
struct ADVISE * pAdvise;
if (!(pAdvise = FindAdvise(hwndServerDDE, nItem)))
return;
pAdvise->bAwaitingAck = FALSE;
GlobalDeleteAtom(pAdvise->atomItem);
GlobalFree(pAdvise->hData);
return;
}
/****************************************************************************
FUNCTION: IsConvInTerminateState
PURPOSE: Terminate whether conversation with specified client is
in process of being terminated.
****************************************************************************/
BOOL IsConvInTerminateState(hwndServerDDE)
HWND hwndServerDDE;
{
struct CONV * pConv;
if (pConv = FindConv(hwndServerDDE))
return (pConv->bInClientRequestedTerminate);
else
return (FALSE);
}
/****************************************************************************
FUNCTION: RemoveAdvise
PURPOSE: Cancel a hot or warm link for a specified conversation item.
If a 0 value is specified for nItem, then all hot/warm links
for the specified client are removed.
****************************************************************************/
BOOL RemoveAdvise(hwndServerDDE, nItem)
HWND hwndServerDDE;
int nItem;
{
struct ADVISE * pAdvise;
int nAdviseIndex;
int nRemoveCount;
nRemoveCount = 0;
for (nAdviseIndex = 0, pAdvise = Advise;
nAdviseIndex < nAdviseCount;
nAdviseIndex++, pAdvise++)
{
if (nRemoveCount)
{
*(pAdvise-nRemoveCount) = *pAdvise;
}
if (pAdvise->hwndServerDDE == hwndServerDDE
&& (!nItem || pAdvise->nItem == nItem))
{
nRemoveCount++;
}
}
if (nRemoveCount)
{
nAdviseCount -= nRemoveCount;
return (TRUE);
}
else
{
return (FALSE);
}
}
/****************************************************************************
FUNCTION: RemoveConv
PURPOSE: Remove conversation from conversation list, and remove
all hot/warm links associated with that conversation
from the advisory list.
****************************************************************************/
void RemoveConv(hwndServerDDE)
HWND hwndServerDDE;
{
struct CONV * pConv;
int nConvIndex;
struct ADVISE * pAdvise;
struct ADVISE * pAdviseShift;
int nAdviseIndex;
int nAdviseDecrement;
for (nConvIndex = 0, pConv = Conv;
nConvIndex < nConvCount;
nConvIndex++, pConv++)
{
if (pConv->hwndServerDDE == hwndServerDDE)
break;
}
nConvCount--;
while (nConvIndex < nConvCount)
{
*pConv = *(pConv+1);
nConvIndex++;
pConv++;
}
/* Remove each hot/warm link */
pAdviseShift = Advise;
nAdviseDecrement = 0;
for (nAdviseIndex = 0, pAdvise = Advise;
nAdviseIndex < nAdviseCount;
nAdviseIndex++, pAdvise++)
{
if (pAdvise->hwndServerDDE == hwndServerDDE)
{
nAdviseDecrement++;
if (pAdvise->bAwaitingAck)
{ /* Destroy objects perhaps not destroyed by client */
GlobalDeleteAtom(pAdvise->atomItem);
GlobalFree(pAdvise->hData);
}
}
else
{
*(pAdviseShift++) = *pAdvise;
}
}
nAdviseCount -= nAdviseDecrement;
return;
}
/****************************************************************************
FUNCTION: SetConvInTerminateState
PURPOSE: Set conversations's terminate state to TRUE.
****************************************************************************/
void SetConvInTerminateState(hwndServerDDE)
HWND hwndServerDDE;
{
struct CONV * pConv;
if (pConv = FindConv(hwndServerDDE))
pConv->bInClientRequestedTerminate = TRUE;
return;
}
SERVDDE.C
CD-ROM Disc Path: \SAMPCODE\WIN_SDK\DDE\SERVDDE.C
/****************************************************************************
MODULE: SERVDDE.C
PURPOSE: Processes incoming and outgoing DDE messages
****************************************************************************/
#include "windows.h"
#include "dde.h"
#include "server.h"
#include <string.h>
#define DEFAULT_ACK_TIME_OUT_MILLISEC 10000
static int nAckTimeOut;
static BOOL bTerminating = FALSE;
int NEAR GetDocIndexGivenName(char*);
int NEAR GetItemNumber(char*);
/****************************************************************************
FUNCTION: DDEWndProc
PURPOSE: Handles all DDE messages received by the server application.
****************************************************************************/
long FAR PASCAL DDEWndProc(hwnd, message, wParam, lParam)
HWND hwnd;
unsigned message;
WORD wParam;
LONG lParam;
{
switch (message)
{
case WM_DDE_ACK:
ServerAcknowledge(hwnd, (HWND)wParam, lParam);
return (0L);
case WM_TIMER: /* time out on waiting for ACK in response */
/* to WM_DDE_DATA sent by this server */
ServerAcknowledge(hwnd, (HWND)wParam, 0L); /* simulates NACK */
return (0L);
case WM_DDE_ADVISE:
ServerAdvise(hwnd, (HWND)wParam, lParam);
return (0L);
case WM_DDE_POKE:
ServerPoke(hwnd, (HWND)wParam, lParam);
return (0L);
case WM_DDE_TERMINATE:
ServerTerminate(hwnd, (HWND)wParam);
return (0L);
case WM_DDE_UNADVISE:
ServerUnadvise(hwnd, (HWND)wParam, lParam);
return (0L);
case WM_DDE_REQUEST:
ServerRequest(hwnd, (HWND)wParam, lParam);
return (0L);
case WM_DDE_EXECUTE:
ServerExecute(hwnd, (HWND)wParam, (HANDLE)HIWORD(lParam));
return (0L);
default:
return (DefWindowProc(hwnd, message, wParam, lParam));
}
}
/****************************************************************************
FUNCTION: GetItemNumber
PURPOSE: Get server control i.d. (1, 2, or 3) given item name.
****************************************************************************/
int NEAR GetItemNumber(szItem)
char * szItem;
{
int nItem;
if (!strcmpi(szItem, "ITEM1"))
nItem = 1;
else if (!strcmpi(szItem, "ITEM2"))
nItem = 2;
else if (!strcmpi(szItem, "ITEM3"))
nItem = 3;
else
nItem = 0;
return (nItem);
}
/****************************************************************************
FUNCTION: InitAckTimeOut
PURPOSE: Get DDE timeout value from win.ini. Value is in milliseconds.
****************************************************************************/
void InitAckTimeOut(void)
{
/* Finds value in win.ini section corresponding to application name */
nAckTimeOut = GetPrivateProfileInt("Server",
"DdeTimeOut",
DEFAULT_ACK_TIME_OUT_MILLISEC,
"server.ini");
return;
}
/****************************************************************************
FUNCTION: SendData
PURPOSE: Send data to client.
****************************************************************************/
void SendData(hwndServerDDE, hwndClientDDE, szItemName, szItemValue,
bDeferUpdate, bAckRequest)
HWND hwndServerDDE;
HWND hwndClientDDE;
char * szItemName;
char * szItemValue;
BOOL bDeferUpdate;
BOOL bAckRequest;
{
ATOM atomItem;
HANDLE hData;
DDEDATA FAR * lpData;
int nItem;
if (bDeferUpdate)
{
atomItem = GlobalAddAtom((LPSTR)szItemName);
/* notify client with null data since advise was set up for */
/* deferred update */
if (!PostMessage(hwndClientDDE,
WM_DDE_DATA,
hwndServerDDE,
MAKELONG(0, atomItem)))
{
GlobalDeleteAtom(atomItem);
}
return;
}
/* Allocate size of DDE data header, plus the data: a string, */
/* <CR> <LR> <NULL>. The byte for the string null terminator */
/* is counted by DDEDATA.Value[1]. */
if (!(hData = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE,
(LONG)sizeof(DDEDATA) +lstrlen(szItemValue) + 2)))
return;
if (!(lpData = (DDEDATA FAR*)GlobalLock(hData)))
{
GlobalFree(hData);
return;
}
lpData->fAckReq = bAckRequest;
lpData->cfFormat = CF_TEXT;
lstrcpy((LPSTR)lpData->Value, (LPSTR)szItemValue);
/* each line of CF_TEXT data is terminated by CR/LF */
lstrcat((LPSTR)lpData->Value, (LPSTR)"\r\n");
GlobalUnlock(hData);
atomItem = GlobalAddAtom((LPSTR)szItemName);
if (!PostMessage(hwndClientDDE,
WM_DDE_DATA,
hwndServerDDE,
MAKELONG(hData, atomItem)))
{
GlobalFree(hData);
GlobalDeleteAtom(atomItem);
return;
}
if (bAckRequest)
{
SetTimer(hwndServerDDE, hwndClientDDE, nAckTimeOut, NULL);
nItem = GetItemNumber(szItemName);
/* hData is to be deleted if not read by client for some reason */
CheckOutSentData(hwndServerDDE, nItem, atomItem, hData);
}
return;
}
/****************************************************************************
FUNCTION: SendTerminate
PURPOSE: Post terminate message and indicate that conversation is
in process ot being terminated.
****************************************************************************/
void SendTerminate(hwndServerDDE, hwndClientDDE)
HWND hwndServerDDE;
HWND hwndClientDDE;
{
SetConvInTerminateState(hwndServerDDE);
PostMessage(hwndClientDDE, WM_DDE_TERMINATE, hwndServerDDE, 0L);
return;
}
/****************************************************************************
FUNCTION: ServerAcknowledge
PURPOSE: Called when server application receives ACK or NACK, or
when server receives time out waiting for response to
WM_DDE_DATA.
****************************************************************************/
void ServerAcknowledge(hwndServerDDE, hwndClientDDE, lParam)
HWND hwndServerDDE;
HWND hwndClientDDE;
LONG lParam;
{
char szItemName[ITEM_NAME_MAX_SIZE+1];
int nItem;
KillTimer(hwndServerDDE, hwndClientDDE);
if (!(LOWORD(lParam) & 0x8000))
{
GlobalGetAtomName(HIWORD(lParam), szItemName, ITEM_NAME_MAX_SIZE);
nItem = GetItemNumber(szItemName);
GlobalFreeSentData(hwndServerDDE, nItem);
MessageBox(hwndMain,
"DDE send data failed",
"Server",
MB_ICONEXCLAMATION | MB_OK);
}
if (HIWORD(lParam)) /* 0 if time-out, so don't try to delete */
GlobalDeleteAtom(HIWORD(lParam));
return;
}
/****************************************************************************
FUNCTION: ServerAdvise
PURPOSE: Called when server application receives WM_DDE_ADVISE message.
****************************************************************************/
void ServerAdvise(hwndServerDDE, hwndClientDDE, lParam)
HWND hwndServerDDE;
HWND hwndClientDDE;
LONG lParam;
{
HANDLE hDDEAdviseOptions;
DDEADVISE FAR * lpDDEAdviseOptions;
ATOM atomItem;
char szItem[ITEM_NAME_MAX_SIZE+1];
int nItem;
hDDEAdviseOptions = LOWORD(lParam);
atomItem = HIWORD(lParam);
GlobalGetAtomName(atomItem, szItem, ITEM_NAME_MAX_SIZE);
if (!(nItem = GetItemNumber(szItem))
|| !AddAdvise(hwndServerDDE, hDDEAdviseOptions, atomItem, nItem))
{
PostMessage(hwndClientDDE,
WM_DDE_ACK,
hwndServerDDE,
MAKELONG(0, atomItem)); /* negative acknowledgement */
return;
}
PostMessage(hwndClientDDE,
WM_DDE_ACK,
hwndServerDDE,
MAKELONG(0x8000, atomItem)); /* positive acknowledgement */
return;
}
/****************************************************************************
FUNCTION: ServerExecute
PURPOSE: Called when server application receives WM_DDE_EXECUTE message.
****************************************************************************/
void ServerExecute(hwndServerDDE, hwndClientDDE, hCommand)
HWND hwndServerDDE;
HWND hwndClientDDE;
HANDLE hCommand;
{
LPSTR lpstrCommand;
char szExecuteString[EXECUTE_STRING_MAX_SIZE+1];
if (!(lpstrCommand = GlobalLock(hCommand)))
{
PostMessage(hwndClientDDE,
WM_DDE_ACK,
hwndServerDDE,
MAKELONG(0, hCommand)); /* negative acknowledgement */
return;
}
if (lstrlen(lpstrCommand) > EXECUTE_STRING_MAX_SIZE)
lpstrCommand[EXECUTE_STRING_MAX_SIZE] = 0;
lstrcpy(szExecuteString, lpstrCommand);
GlobalUnlock(hCommand);
PostMessage(hwndClientDDE,
WM_DDE_ACK,
hwndServerDDE,
MAKELONG(0x8000, hCommand)); /* positive acknowledgement */
MessageBox(hwndMain,
szExecuteString,
"Server Received Execute Command",
MB_OK);
return;
}
/****************************************************************************
FUNCTION: ServerInitiate
PURPOSE: Called when server application receives WM_DDE_INITIATE message
****************************************************************************/
void ServerInitiate(hwndClientDDE, lParam)
HWND hwndClientDDE;
LONG lParam;
{
HWND hwndServerDDE;
ATOM atomApplicationRcvd;
ATOM atomTopicRcvd;
ATOM atomApplicationReturn;
ATOM atomTopicReturn;
char szApplication[APP_MAX_SIZE+1];
char szTopic[TOPIC_MAX_SIZE+1];
if (!(hwndServerDDE = CreateWindow(
"ServerDDEWndClass",
"ServerDDE",
WS_CHILD, /* not visible */
0, 0, 0, 0, /* no position or dimensions */
hwndMain, /* parent */
NULL, /* no menu */
hInst,
NULL)))
{
return;
}
if (atomApplicationRcvd = LOWORD(lParam))
GlobalGetAtomName(atomApplicationRcvd, szApplication, APP_MAX_SIZE);
if (atomApplicationRcvd && strcmpi(szApplication,"SERVER"))
{ /* if application was specified but it wasn't "server" */
return;
}
if (atomTopicRcvd = HIWORD(lParam))
{
GlobalGetAtomName(atomTopicRcvd, szTopic, TOPIC_MAX_SIZE);
if (strcmpi(szTopic, szDocName))
return;
}
if (AddConv(hwndServerDDE, hwndClientDDE))
{
atomApplicationReturn = GlobalAddAtom("SERVER");
atomTopicReturn = GlobalAddAtom(szDocName);
if (!SendMessage(hwndClientDDE,
WM_DDE_ACK,
hwndServerDDE,
MAKELONG(atomApplicationReturn, atomTopicReturn)))
{
GlobalDeleteAtom(atomApplicationReturn);
GlobalDeleteAtom(atomTopicReturn);
}
}
return;
}
/****************************************************************************
FUNCTION: ServerPoke
PURPOSE: Called when server application receives WM_DDE_POKE message.
****************************************************************************/
void ServerPoke(hwndServerDDE, hwndClientDDE, lParam)
HWND hwndServerDDE;
HWND hwndClientDDE;
LONG lParam;
{
HANDLE hPokeData;
DDEPOKE FAR * lpPokeData;
ATOM atomItem;
int nItem;
char szItemName[ITEM_NAME_MAX_SIZE+1];
char szItemValue[ITEM_VALUE_MAX_SIZE+1];
BOOL bRelease;
char * pcCarriageReturn;
hPokeData = LOWORD(lParam);
atomItem = HIWORD(lParam);
GlobalGetAtomName(atomItem, szItemName, ITEM_NAME_MAX_SIZE);
if (!(lpPokeData = (DDEPOKE FAR *)GlobalLock(hPokeData))
|| lpPokeData->cfFormat != CF_TEXT
|| !(nItem = GetItemNumber(szItemName)))
{
PostMessage(hwndClientDDE,
WM_DDE_ACK,
hwndServerDDE,
MAKELONG(0, atomItem)); /* negative acknowledgement */
return;
}
lstrcpy(szItemValue, lpPokeData->Value);
if (pcCarriageReturn = strchr(szItemValue, '\r'))
*pcCarriageReturn = 0; /* remove CR/LF */
SetDlgItemText(hwndMain, nItem, szItemValue);
MaybeAdviseData(nItem);
/* Save value of fRelease, since pointer may be invalidated by */
/* GlobalUnlock() */
bRelease = lpPokeData->fRelease;
GlobalUnlock(hPokeData);
if (bRelease)
{
GlobalFree(hPokeData);
}
/* Since we are re-using the item atom, we should not delete it */
/* if PostMessage fails: the client should delete the atom */
/* when it gets a time-out on the expected ACK. */
PostMessage(hwndClientDDE,
WM_DDE_ACK,
hwndServerDDE,
MAKELONG(0x8000, atomItem)); /* positive acknowledgement */
return;
}
/****************************************************************************
FUNCTION: ServerRequest
PURPOSE: Called when server application receives WM_DDE_REQUEST message.
****************************************************************************/
void ServerRequest(hwndServerDDE, hwndClientDDE, lParam)
HWND hwndServerDDE;
HWND hwndClientDDE;
LONG lParam;
{
char szItem[ITEM_NAME_MAX_SIZE+1];
char szItemValue[ITEM_VALUE_MAX_SIZE+1];
int nItem;
GlobalGetAtomName(HIWORD(lParam), szItem, ITEM_NAME_MAX_SIZE);
if (!(nItem = GetItemNumber(szItem))
|| (LOWORD(lParam) != CF_TEXT)) /* this app supports only CF_TEXT */
{
PostMessage(hwndClientDDE,
WM_DDE_ACK,
hwndServerDDE,
MAKELONG(0, HIWORD(lParam))); /* NACK */
return;
}
if (!GetDlgItemText(hwndMain, nItem, szItemValue, ITEM_VALUE_MAX_SIZE))
{
strcpy(szItemValue," ");
}
/* send now, don't defer, and don't ask for ACK */
SendData(hwndServerDDE, hwndClientDDE, szItem, szItemValue, FALSE, FALSE)
GlobalDeleteAtom(HIWORD(lParam));
return;
}
/****************************************************************************
FUNCTION: ServerTerminate
PURPOSE: Called when server application receives WM_DDE_TERMINATE messag
****************************************************************************/
void ServerTerminate(hwndServerDDE, hwndClientDDE)
HWND hwndServerDDE;
HWND hwndClientDDE;
{
if (!IsConvInTerminateState(hwndClientDDE))
{ /* Client has requested terminate: respond with terminate */
PostMessage(hwndClientDDE, WM_DDE_TERMINATE, hwndServerDDE, 0L);
}
RemoveConv(hwndServerDDE);
DestroyWindow(hwndServerDDE);
return;
}
/****************************************************************************
FUNCTION: ServerUnadvise
PURPOSE: Called when server application receives WM_DDE_UNADIVSE message
****************************************************************************/
void ServerUnadvise(hwndServerDDE, hwndClientDDE, lParam)
HWND hwndServerDDE;
HWND hwndClientDDE;
LONG lParam;
{
char szItem[ITEM_NAME_MAX_SIZE+1];
int nItem;
BOOL bSuccess;
if (HIWORD(lParam))
{
GlobalGetAtomName(HIWORD(lParam), szItem, ITEM_NAME_MAX_SIZE);
nItem = GetItemNumber(szItem);
bSuccess = RemoveAdvise(hwndServerDDE, nItem);
}
else
{ /* HIWORD(lParam)==0 means remove all advises */
bSuccess = RemoveAdvise(hwndServerDDE, 0);
}
if (bSuccess)
{
PostMessage(hwndClientDDE,
WM_DDE_ACK,
hwndServerDDE,
MAKELONG(0x8000, HIWORD(lParam))); /* positive ack */
}
else
{
PostMessage(hwndClientDDE,
WM_DDE_ACK,
hwndServerDDE,
MAKELONG(0, HIWORD(lParam))); /* negative ack */
}
return;
}
/****************************************************************************
FUNCTION: TerminateConversations
PURPOSE: Processes WM_DESTROY message, terminates all conversations.
****************************************************************************/
void TerminateConversations()
{
HWND hwndServerDDE;
LONG lTimeOut;
MSG msg;
/* Terminate each active conversation */
hwndServerDDE = NULL;
while (hwndServerDDE = GetNextConv(hwndServerDDE))
{
SendTerminate(hwndServerDDE, GetHwndClientDDE(hwndServerDDE));
}
/* Wait for all conversations to terminate OR for time out */
lTimeOut = GetTickCount() + (LONG)nAckTimeOut;
while (PeekMessage(&msg, NULL, WM_DDE_FIRST, WM_DDE_LAST, PM_REMOVE))
{
DispatchMessage (&msg);
if (msg.message == WM_DDE_TERMINATE)
{
if (!AtLeastOneConvActive())
break;
}
if (GetTickCount() > lTimeOut)
break;
}
return;
}
SERVER.C
CD-ROM Disc Path: \SAMPCODE\WIN_SDK\DDE\SERVER.C
/***************************************************************************
PROGRAM: SERVER
PURPOSE: Illustrates server side of DDE conversation
MODULES:
SERVER.C Window and dialog procedures.
SERVDATA.C Maintains conversation information.
SERVDDE.C Processes incoming and outgoing DDE messages.
****************************************************************************/
#include "windows.h"
#include "dde.h"
#include "server.h"
#include "servres.h"
#include <string.h>
#include <stdlib.h>
static int xDelta;
static int yDelta;
long FAR PASCAL MainWndProc(HWND, unsigned, WORD, LONG);
BOOL InitApplication(HANDLE);
void InitAddedInstance(HANDLE, HANDLE);
BOOL InitInstance(HANDLE, int);
void MaybeAdviseData(int);
BOOL FAR PASCAL AboutDlgProc(HWND, unsigned, WORD, LONG);
/****************************************************************************
FUNCTION: WinMain(HANDLE, HANDLE, LPSTR, int)
PURPOSE: Calls initialization function, processes message loop
****************************************************************************/
int PASCAL WinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow)
HANDLE hInstance;
HANDLE hPrevInstance;
LPSTR lpCmdLine;
int nCmdShow;
{
MSG msg;
HANDLE hAccel;
if (!hPrevInstance)
{
if (!InitApplication(hInstance))
return (FALSE);
}
else
{
InitAddedInstance(hInstance, hPrevInstance);
}
if (!InitInstance(hInstance, nCmdShow))
return (FALSE);
hAccel = LoadAccelerators(hInstance, "ServerAcc");
while (GetMessage(&msg, NULL, NULL, NULL))
{
if (!TranslateAccelerator(hwndMain, hAccel, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return (msg.wParam);
}
/****************************************************************************
FUNCTION: InitApplication(HANDLE)
PURPOSE: Initializes window data and registers window class
****************************************************************************/
BOOL InitApplication(hInstance)
HANDLE hInstance;
{
WNDCLASS wc;
nDoc = 1;
wc.style = NULL;
wc.lpfnWndProc = MainWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = "ServerMenu";
wc.lpszClassName = "ServerWClass";
if (!RegisterClass(&wc))
return (FALSE);
wc.style = NULL;
wc.lpfnWndProc = DDEWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = NULL;
wc.hCursor = NULL;
wc.hbrBackground = NULL;
wc.lpszMenuName = NULL;
wc.lpszClassName = "ServerDDEWndClass";
return (RegisterClass(&wc));
}
/****************************************************************************
FUNCTION: InitAddedInstance
PURPOSE: Increment document number
****************************************************************************/
void InitAddedInstance(hInstance, hPrevInstance)
HANDLE hInstance;
HANDLE hPrevInstance;
{
GetInstanceData(hPrevInstance, (NPSTR)&nDoc, sizeof(int));
nDoc++;
return;
}
/****************************************************************************
FUNCTION: InitInstance(HANDLE, int)
PURPOSE: Saves instance handle, creates main window, and creates
3 child edit controls with id's 1, 2, and 3.
****************************************************************************/
BOOL InitInstance(hInstance, nCmdShow)
HANDLE hInstance;
int nCmdShow;
{
char szNumber[4];
char szCaption[20];
HDC hDC;
PAINTSTRUCT ps;
TEXTMETRIC tm;
int nItem;
int nHorzRes, nVertRes;
InitAckTimeOut(); /* in module SERVDDE */
hInst = hInstance;
strcpy(szDocName, "FILE");
itoa(nDoc, szNumber, 10);
strcat(szDocName, szNumber);
strcpy(szCaption, "Server -- ");
strcat(szCaption, szDocName);
hwndMain = CreateWindow(
"ServerWClass",
szCaption,
WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
hInstance,
NULL
);
if (!hwndMain)
return (FALSE);
hDC = GetDC(hwndMain);
GetTextMetrics(hDC, (LPTEXTMETRIC)&tm);
xDelta = tm.tmAveCharWidth;
yDelta = tm.tmHeight + tm.tmExternalLeading;
nHorzRes = GetDeviceCaps(hDC, HORZRES);
nVertRes = GetDeviceCaps(hDC, VERTRES);
ReleaseDC(hwndMain, hDC);
MoveWindow(hwndMain,
nHorzRes/2 + xDelta*(nDoc+5),
((nDoc-1)&1)*nVertRes/2 + yDelta*nDoc,
xDelta*30,
yDelta*12,
FALSE);
for (nItem = 1; nItem < 4; nItem++)
{
CreateWindow("edit", NULL,
WS_CHILD | WS_VISIBLE | WS_BORDER | ES_LEFT | WS_TABSTOP,
9*xDelta, (2*nItem-1)*yDelta, 12*xDelta, (yDelta*3)/2,
hwndMain, nItem, hInst, NULL);
}
if (!(cfLink = RegisterClipboardFormat("Link")))
return (FALSE);
ShowWindow(hwndMain, nCmdShow);
UpdateWindow(hwndMain);
return (TRUE);
}
/****************************************************************************
FUNCTION: MainWndProc(HWND, unsigned, WORD, LONG)
PURPOSE: Processes messages for server
****************************************************************************/
long FAR PASCAL MainWndProc(hwnd, message, wParam, lParam)
HWND hwnd;
unsigned message;
WORD wParam;
LONG lParam;
{
HDC hDC;
PAINTSTRUCT ps;
HWND hctlItem;
int nItem;
char szItemName[8];
FARPROC lpAboutDlgProc;
switch (message)
{
case WM_SETFOCUS:
SetFocus(GetDlgItem(hwnd,1));
break;
case WM_PAINT:
hDC = BeginPaint(hwnd, &ps);
strcpy(szItemName, "Item1:");
for (nItem = 1; nItem < 4; nItem++)
{
/* display labels for the edit controls */
TextOut(hDC, xDelta, (2*nItem-1)*yDelta, szItemName, 6);
szItemName[4]++;
}
EndPaint(hwnd, &ps);
break;
case WM_COMMAND:
switch (wParam)
{
case IDM_COPY:
hctlItem = GetFocus();
for (nItem = 1; nItem <= 3; nItem++)
{
if (hctlItem == GetDlgItem(hwnd, nItem))
{
DoEditCopy(nItem);
break;
}
}
break;
case ID_TAB:
case ID_SHIFT_TAB:
if (IsChild(hwndMain, GetFocus()))
{
nItem = GetWindowWord(GetFocus(), GWW_ID);
if (wParam == ID_TAB)
{
if (nItem++ == 3)
nItem = 1;
}
else
{
if (nItem-- == 1)
nItem = 3;
}
}
else
{
nItem = 1;
}
SetFocus(GetDlgItem(hwndMain, nItem));
break;
case 1:
case 2:
case 3:
if (HIWORD(lParam)==EN_KILLFOCUS)
{
hctlItem = GetDlgItem(hwnd, wParam);
if (SendMessage(hctlItem, EM_GETMODIFY, 0, 0L))
{
MaybeAdviseData(wParam);
SendMessage(hctlItem, EM_SETMODIFY, 0, 0L);
}
}
break;
case IDM_ABOUT:
lpAboutDlgProc = MakeProcInstance(AboutDlgProc, hInst);
DialogBox(hInst,
"About",
hwndMain,
lpAboutDlgProc);
FreeProcInstance(lpAboutDlgProc);
break;
}
break;
case WM_DDE_INITIATE:
ServerInitiate((HWND)wParam, lParam);
break;
case WM_DESTROY:
/* Terminate all DDE conversations before destroying
client window */
TerminateConversations();
PostQuitMessage(0);
break;
default:
return (DefWindowProc(hwnd, message, wParam, lParam));
}
return (0L);
}
/****************************************************************************
FUNCTION: MaybeAdviseData
PURPOSE: Send data to all clients for which a hot or warm link
has been established for the specified item.
****************************************************************************/
void MaybeAdviseData(nItem)
int nItem;
{
HWND hwndServerDDE;
char szItemName[ITEM_NAME_MAX_SIZE+1];
char szItemValue[ITEM_VALUE_MAX_SIZE+1];
BOOL bDeferUpdate;
BOOL bAckRequest;
hwndServerDDE = NULL;
while (1)
{
if (hwndServerDDE = GetNextAdvise(hwndServerDDE, nItem))
{
GetAdviseData(hwndServerDDE,
nItem,
szItemName,
szItemValue,
&bDeferUpdate,
&bAckRequest);
SendData(hwndServerDDE,
GetHwndClientDDE(hwndServerDDE),
szItemName,
szItemValue,
bDeferUpdate,
bAckRequest);
}
else return;
}
}
/****************************************************************************
FUNCTION: AboutDlgProc(HWND, unsigned, WORD, LONG)
PURPOSE: Processes messages for "About" dialog box
****************************************************************************/
BOOL FAR PASCAL AboutDlgProc(hDlg, message, wParam, lParam)
HWND hDlg;
unsigned message;
WORD wParam;
LONG lParam;
{
switch (message) {
case WM_INITDIALOG:
return (TRUE);
case WM_COMMAND:
if (wParam == IDOK || wParam == IDCANCEL) {
EndDialog(hDlg, TRUE);
return (TRUE);
}
break;
}
return (FALSE);
}
SHOWDIB.C
CD-ROM Disc Path: \SAMPCODE\WIN_SDK\SHOWDIB\SHOWDIB.C
/****************************************************************************
* *
* PROGRAM : ShowDIB.c *
* *
* PURPOSE : Application to illustrate the use of the GDI *
* DIB (Device Independent Bitmap) and Palette manager *
* functions. *
* *
* FUNCTIONS : WinMain () - Creates the app. window and enters *
* the message loop. *
* *
* WndProc() - Processes app. window messages. *
* *
* MenuCommand() - Processes menu commands. *
* *
* FreeDIB() - Frees currently active objects. *
* *
* InitDIB() - Reads DIB from a file and loads it.*
* *
****************************************************************************
#include <windows.h>
#include <io.h>
#include <stdio.h>
#include "showdib.h"
DIBPARAMS DIBParams; /* params for the SETSCALING escape */
char achFileName[128] = "";
DWORD dwOffset;
NPLOGPALETTE pLogPal;
HPALETTE hpalSave = NULL;
HANDLE hInst ;
RECT rcClip;
extern WORD _WinFlags;
static HCURSOR hcurSave;
BOOL fPalColors = FALSE; /* TRUE if the current DIB's color table
/* contains palette indexes not rgb values */
WORD nAnimating = 0; /* Palette animation count */
WORD UpdateCount = 0;
BOOL bMemoryDIB = FALSE; /* Load Entire DIB into memory in CF_DIB format
BOOL bUpdateColors = TRUE; /* Directly update screen colors */
BOOL bDIBToDevice = FALSE; /* Use SetDIBitsToDevice() to BLT data.
BOOL bNoUgly = FALSE; /* Make window black on a WM_PALETTEISCHANGING
BOOL bLegitDraw = FALSE; /* We have a valid bitmap to draw */
char szBitmapExt[] = "*.BMP; *.DIB; *.RLE"; /* possible file extensions
WORD wTransparent = TRANSPARENT; /* Mode of DC */
char szAppName[] = "ShowDIB" ; /* App. name */
HPALETTE hpalCurrent = NULL; /* Handle to current palette *
HANDLE hdibCurrent = NULL; /* Handle to current memory DIB
HBITMAP hbmCurrent = NULL; /* Handle to current memory BITMAP
HANDLE hbiCurrent = NULL; /* Handle to current bitmap info struc
HWND hWndApp; /* Handle to app. window */
/* Styles of app. window */
DWORD dwStyle = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU |
WS_MAXIMIZEBOX | WS_MINIMIZEBOX | WS_THICKFRAME;
void PrintDIB (HWND hWnd, HDC hDC, int x, int y, int dx, int dy);
/****************************************************************************
* *
* FUNCTION : WinMain(HANDLE, HANDLE, LPSTR, int) *
* *
* PURPOSE : Creates the app. window and enters the message loop. *
* *
****************************************************************************
int PASCAL WinMain (hInstance, hPrevInstance, lpszCmdLine, nCmdShow)
HANDLE hInstance, hPrevInstance ;
LPSTR lpszCmdLine ;
int nCmdShow ;
{
HWND hWnd ;
WNDCLASS wndclass ;
MSG msg ;
short xScreen, yScreen ;
char ach[40];
hInst = hInstance ;
/* default to MEMORY DIB's if XWindows */
bMemoryDIB = WinFlags & WF_PMODE;
/* Initialize clip rectangle */
SetRectEmpty(&rcClip);
if (!hPrevInstance) {
wndclass.style = CS_DBLCLKS;
wndclass.lpfnWndProc = WndProc ;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hInstance = hInstance ;
wndclass.hIcon = LoadIcon(hInst, "SHOWICON");
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = GetStockObject (BLACK_BRUSH) ;
wndclass.lpszMenuName = szAppName ;
wndclass.lpszClassName = szAppName ;
if (!RegisterClass (&wndclass))
return FALSE ;
}
if (!GetProfileString("extensions", "bmp", "", ach, sizeof(ach)))
WriteProfileString("extensions", "bmp", "showdib.exe ^.bmp");
if (!GetProfileString("extensions", "dib", "", ach, sizeof(ach)))
WriteProfileString("extensions", "dib", "showdib.exe ^.dib");
/* Save the pointer to the command line */
lstrcpy(achFileName, lpszCmdLine);
xScreen = GetSystemMetrics (SM_CXSCREEN) ;
yScreen = GetSystemMetrics (SM_CYSCREEN) ;
/* Create the app. window */
hWnd = CreateWindow( szAppName,
szAppName,
dwStyle,
CW_USEDEFAULT,
0,
xScreen / 2,
yScreen / 2,
NULL,
NULL,
hInstance,
NULL) ;
ShowWindow (hWndApp = hWnd, nCmdShow) ;
/* Enter message loop */
while (GetMessage (&msg, NULL, 0, 0)) {
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
return msg.wParam ;
}
/****************************************************************************
* *
* FUNCTION : WndProc (hWnd, iMessage, wParam, lParam) *
* *
* PURPOSE : Processes window messages. *
* *
****************************************************************************
long FAR PASCAL WndProc (hWnd, iMessage, wParam, lParam)
HWND hWnd ;
unsigned iMessage ;
WORD wParam ;
LONG lParam ;
{
PAINTSTRUCT ps;
HDC hDC;
HANDLE h;
int i;
int iMax;
int iMin;
int iPos;
int dn;
RECT rc,Rect;
HPALETTE hOldPal;
HMENU hMenu;
switch (iMessage) {
case WM_DESTROY:
/* Clean up and quit */
FreeDib();
PostQuitMessage(0);
break ;
case WM_CREATE:
/* Allocate space for our logical palette */
pLogPal = (NPLOGPALETTE) LocalAlloc( LMEM_FIXED,
(sizeof(LOGPALETTE) +
(sizeof(PALETTEENTRY)*(MAXPALETTE))));
/* If DIB initialization fails, quit */
if (achFileName[0] && !InitDIB(hWnd))
PostQuitMessage (3) ;
/* fall through */
case WM_WININICHANGE:
hMenu = GetMenu(hWnd);
/* If printer initialization succeeds, enable appropriate
* menu item and clean up.
*/
if ( hDC = GetPrinterDC() ) {
EnableMenuItem( hMenu,
IDM_PRINT,
(RC_DIBTODEV &
GetDeviceCaps(hDC, RASTERCAPS)) ?
MF_ENABLED :
MF_GRAYED | MF_DISABLED);
DeleteDC(hDC);
}
break;
case WM_PALETTEISCHANGING:
/* if SHOWDIB was not responsible for palette change and if
* ok to hide changes, paint app. window black.
*/
if (wParam != hWnd && bNoUgly) {
GetClientRect(hWnd, &Rect);
hDC = GetDC(hWnd);
FillRect( hDC, (LPRECT) &Rect, GetStockObject(BLACK_BRUSH));
ReleaseDC(hWnd, hDC);
}
break;
case WM_ACTIVATE:
if (!wParam) /* app. is being de-activated */
break;
/* If the app. is moving to the foreground, fall through and
* redraw full client area with the newly realized palette,
* if the palette has changed.
*/
case WM_QUERYNEWPALETTE:
/* If palette realization causes a palette change,
* we need to do a full redraw.
*/
if (bLegitDraw) {
hDC = GetDC (hWnd);
hOldPal = SelectPalette (hDC, hpalCurrent, 0);
i = RealizePalette(hDC);
SelectPalette (hDC, hOldPal, 0);
ReleaseDC (hWnd, hDC);
if (i) {
InvalidateRect (hWnd, (LPRECT) (NULL), 1);
UpdateCount = 0;
return 1;
} else
return FALSE;
}
else
return FALSE;
break;
case WM_PALETTECHANGED:
/* if SHOWDIB was not responsible for palette change and if
* palette realization causes a palette change, do a redraw.
*/
if (wParam != hWnd){
if (bLegitDraw){
hDC = GetDC (hWnd);
hOldPal = SelectPalette (hDC, hpalCurrent, 0);
i = RealizePalette (hDC);
if (i){
if (bUpdateColors){
UpdateColors (hDC);
UpdateCount++;
}
else
InvalidateRect (hWnd, (LPRECT) (NULL), 1);
}
SelectPalette (hDC, hOldPal, 0);
ReleaseDC (hWnd, hDC);
}
}
break;
case WM_RENDERALLFORMATS:
/* Ensure that clipboard data can be rendered even tho'
* app. is being destroyed.
*/
SendMessage(hWnd,WM_RENDERFORMAT,CF_DIB,0L);
SendMessage(hWnd,WM_RENDERFORMAT,CF_BITMAP,0L);
SendMessage(hWnd,WM_RENDERFORMAT,CF_PALETTE,0L);
break;
case WM_RENDERFORMAT:
/* Format data in manner specified and pass the data
* handle to clipboard.
*/
if (h = RenderFormat(wParam))
SetClipboardData(wParam,h);
break;
case WM_COMMAND:
/* Process menu commands */
return MenuCommand (hWnd, wParam);
break;
case WM_TIMER:
/* Signal for palette animation */
hDC = GetDC(hWnd);
hOldPal = SelectPalette(hDC, hpalCurrent, 0);
{
PALETTEENTRY peTemp;
/* Shift all palette entries left by one position and wrap
* around the first entry
*/
peTemp = pLogPal->palPalEntry[0];
for (i = 0; i < (pLogPal->palNumEntries - 1); i++)
pLogPal->palPalEntry[i] = pLogPal->palPalEntry[i+1];
pLogPal->palPalEntry[i] = peTemp;
}
/* Replace entries in logical palette with new entries*/
AnimatePalette(hpalCurrent, 0, pLogPal->palNumEntries, pLogPal->palPalEnt
SelectPalette(hDC, hOldPal, 0);
ReleaseDC(hWnd, hDC);
/* Decrement animation count and terminate animation
* if it reaches zero
*/
if (!(--nAnimating))
PostMessage(hWnd,WM_COMMAND,IDM_ANIMATE0,0L);
break;
case WM_PAINT:
/* If we have updated more than once, the rest of our
* window is not in some level of degradation worse than
* our redraw... we need to redraw the whole area
*/
if (UpdateCount > 1) {
BeginPaint(hWnd, &ps);
EndPaint(hWnd, &ps);
UpdateCount = 0;
InvalidateRect(hWnd, (LPRECT) (NULL), 1);
break;
}
hDC = BeginPaint(hWnd, &ps);
AppPaint(hWnd,
hDC,
GetScrollPos(hWnd,SB_HORZ),
GetScrollPos(hWnd,SB_VERT) );
EndPaint(hWnd, &ps);
break ;
case WM_SIZE:
SetScrollRanges(hWnd);
break;
case WM_KEYDOWN:
/* Translate keyboard messages to scroll commands */
switch (wParam) {
case VK_UP: PostMessage (hWnd, WM_VSCROLL, SB_LINEUP, 0L);
break;
case VK_DOWN: PostMessage (hWnd, WM_VSCROLL, SB_LINEDOWN, 0L);
break;
case VK_PRIOR: PostMessage (hWnd, WM_VSCROLL, SB_PAGEUP, 0L);
break;
case VK_NEXT: PostMessage (hWnd, WM_VSCROLL, SB_PAGEDOWN, 0L);
break;
case VK_HOME: PostMessage (hWnd, WM_HSCROLL, SB_PAGEUP, 0L);
break;
case VK_END: PostMessage (hWnd, WM_HSCROLL, SB_PAGEDOWN, 0L);
break;
case VK_LEFT: PostMessage (hWnd, WM_HSCROLL, SB_LINEUP, 0L);
break;
case VK_RIGHT: PostMessage (hWnd, WM_HSCROLL, SB_LINEDOWN, 0L);
break;
}
break;
case WM_KEYUP:
switch (wParam) {
case VK_UP:
case VK_DOWN:
case VK_PRIOR:
case VK_NEXT:
PostMessage (hWnd, WM_VSCROLL, SB_ENDSCROLL, 0L);
break;
case VK_HOME:
case VK_END:
case VK_LEFT:
case VK_RIGHT:
PostMessage (hWnd, WM_HSCROLL, SB_ENDSCROLL, 0L);
break;
}
break;
case WM_VSCROLL:
/* Calculate new vertical scroll position */
GetScrollRange (hWnd, SB_VERT, &iMin, &iMax);
iPos = GetScrollPos (hWnd, SB_VERT);
GetClientRect (hWnd, &rc);
switch (wParam) {
case SB_LINEDOWN: dn = rc.bottom / 16 + 1;
break;
case SB_LINEUP: dn = -rc.bottom / 16 + 1;
break;
case SB_PAGEDOWN: dn = rc.bottom / 2 + 1;
break;
case SB_PAGEUP: dn = -rc.bottom / 2 + 1;
break;
case SB_THUMBTRACK:
case SB_THUMBPOSITION: dn = LOWORD(lParam)-iPos;
break;
default: dn = 0;
}
/* Limit scrolling to current scroll range */
if (dn = BOUND (iPos + dn, iMin, iMax) - iPos) {
ScrollWindow (hWnd, 0, -dn, NULL, NULL);
SetScrollPos (hWnd, SB_VERT, iPos + dn, TRUE);
}
break;
case WM_HSCROLL:
/* Calculate new horizontal scroll position */
GetScrollRange (hWnd, SB_HORZ, &iMin, &iMax);
iPos = GetScrollPos (hWnd, SB_HORZ);
GetClientRect (hWnd, &rc);
switch (wParam) {
case SB_LINEDOWN: dn = rc.right / 16 + 1;
break;
case SB_LINEUP: dn = -rc.right / 16 + 1;
break;
case SB_PAGEDOWN: dn = rc.right / 2 + 1;
break;
case SB_PAGEUP: dn = -rc.right / 2 + 1;
break;
case SB_THUMBTRACK:
case SB_THUMBPOSITION: dn = LOWORD (lParam) - iPos;
break;
default: dn = 0;
}
/* Limit scrolling to current scroll range */
if (dn = BOUND (iPos + dn, iMin, iMax) - iPos) {
ScrollWindow (hWnd, -dn, 0, NULL, NULL);
SetScrollPos (hWnd, SB_HORZ, iPos + dn, TRUE);
}
break;
case WM_LBUTTONDOWN:
/* Start rubberbanding a rect. and track it's dimensions.
* set the clip rectangle to it's dimensions.
*/
TrackMouse (hWnd, MAKEPOINT (lParam));
break;
case WM_LBUTTONDBLCLK:
break;
case WM_INITMENU:
/* check/uncheck menu items depending on state of related
* flags
*/
CheckMenuItem(wParam, IDM_UPDATECOL,
(bUpdateColors ? MF_CHECKED : MF_UNCHECKED));
CheckMenuItem(wParam, IDM_TRANSPARENT,
(wTransparent == TRANSPARENT ? MF_CHECKED : MF_UNCHECKED));
CheckMenuItem(wParam, IDM_DIBSCREEN,
(bDIBToDevice ? MF_CHECKED : MF_UNCHECKED));
CheckMenuItem(wParam, IDM_NOUGLY,
(bNoUgly ? MF_CHECKED : MF_UNCHECKED));
CheckMenuItem(wParam, IDM_MEMORYDIB,
(bMemoryDIB ? MF_CHECKED : MF_UNCHECKED));
EnableMenuItem(wParam, IDM_PASTEDIB,
IsClipboardFormatAvailable(CF_DIB)?MF_ENABLED:MF_GRAYED);
EnableMenuItem(wParam, IDM_PASTEDDB,
IsClipboardFormatAvailable(CF_BITMAP)?MF_ENABLED:MF_GRAYED);
EnableMenuItem(wParam, IDM_PASTEPAL,
IsClipboardFormatAvailable(CF_PALETTE)?MF_ENABLED:MF_GRAYED);
EnableMenuItem(wParam, IDM_PRINT,
bLegitDraw ? MF_ENABLED : MF_GRAYED);
EnableMenuItem(wParam, IDM_SAVE,
bLegitDraw ? MF_ENABLED : MF_GRAYED);
EnableMenuItem(wParam, IDM_COPY,
bLegitDraw ? MF_ENABLED : MF_GRAYED);
EnableMenuItem(wParam, IDM_ANIMATE0,
bLegitDraw ? MF_ENABLED : MF_GRAYED);
EnableMenuItem(wParam, IDM_ANIMATE5,
bLegitDraw ? MF_ENABLED : MF_GRAYED);
EnableMenuItem(wParam, IDM_ANIMATE50,
bLegitDraw ? MF_ENABLED : MF_GRAYED);
EnableMenuItem(wParam, IDM_ANIMATE100,
bLegitDraw ? MF_ENABLED : MF_GRAYED);
EnableMenuItem(wParam, IDM_ANIMATE200,
bLegitDraw ? MF_ENABLED : MF_GRAYED);
EnableMenuItem(wParam, IDM_ANIMATE201,
bLegitDraw ? MF_ENABLED : MF_GRAYED);
EnableMenuItem(wParam, IDM_STEALCOL,
bLegitDraw ? MF_ENABLED : MF_GRAYED);
break;
default:
return DefWindowProc (hWnd, iMessage, wParam, lParam) ;
}
return 0L ;
}
/****************************************************************************
* *
* FUNCTION : MenuCommand ( HWND hWnd, WORD wParam) *
* *
* PURPOSE : Processes menu commands. *
* *
* RETURNS : TRUE - if command could be processed. *
* FALSE - otherwise *
* *
****************************************************************************
BOOL MenuCommand (hWnd, id)
HWND hWnd;
WORD id;
{
BITMAPINFOHEADER bi;
HDC hDC;
HANDLE h;
HBITMAP hbm;
HPALETTE hpal;
int i;
char Name[40];
BOOL bSave;
int xSize, ySize, xRes, yRes, dx, dy;
RECT Rect;
int fh;
WORD fFileOptions;
switch (id) {
case IDM_ABOUT:
/* Show About .. box */
fDialog (ABOUTBOX, hWnd,AppAbout);
break;
case IDM_COPY:
if (!bLegitDraw)
return 0L;
/* Clean clipboard of contents */
if (OpenClipboard(hWnd)) {
EmptyClipboard ();
SetClipboardData (CF_DIB ,NULL);
SetClipboardData (CF_BITMAP ,NULL);
SetClipboardData (CF_PALETTE ,NULL);
CloseClipboard ();
}
break;
case IDM_PASTEPAL:
if (OpenClipboard (hWnd)) {
if (h = GetClipboardData (CF_PALETTE)) {
/* Delete current palette and get the CF_PALETTE data
* from the clipboard
*/
if (hpalCurrent)
DeleteObject (hpalCurrent);
hpalCurrent = CopyPalette (h);
/*
* If we have a bitmap realized against the old palette
* delete the bitmap and rebuild it using the new palette.
*/
if (hbmCurrent){
DeleteObject (hbmCurrent);
hbmCurrent = NULL;
if (hdibCurrent)
hbmCurrent = BitmapFromDib (hdibCurrent, hpalCurrent);
}
}
CloseClipboard();
}
break;
case IDM_PASTEDIB:
if (OpenClipboard (hWnd)) {
if (h = GetClipboardData (CF_DIB)) {
/* Delete current DIB and get CF_DIB and
* CF_PALETTE format data from the clipboard
*/
hpal = GetClipboardData (CF_PALETTE);
FreeDib();
hdibCurrent = CopyHandle (h);
if (hdibCurrent) {
bLegitDraw = TRUE;
lstrcpy(achFileName,"<Clipboard>");
hbiCurrent = hdibCurrent;
/* If there is a CF_PALETTE object in the
* clipboard, this is the palette to assume
* the DIB should be realized against, otherwise
* create a palette for it.
*/
if (hpal)
hpalCurrent = CopyPalette (hpal);
else
hpalCurrent = CreateDibPalette (hdibCurrent);
SizeWindow(hWnd);
}
else {
bLegitDraw = FALSE;
ErrMsg("No Memory Available!");
}
}
CloseClipboard();
}
break;
case IDM_PASTEDDB:
if (OpenClipboard (hWnd)) {
if (hbm = GetClipboardData(CF_BITMAP)) {
hpal = GetClipboardData(CF_PALETTE);
FreeDib();
/*
* If there is a CF_PALETTE object in the
* clipboard, this is the palette to assume
* the bitmap is realized against.
*/
if (hpal)
hpalCurrent = CopyPalette(hpal);
else
hpalCurrent = GetStockObject(DEFAULT_PALETTE);
hdibCurrent = DibFromBitmap(hbm,BI_RGB,0,hpalCurrent);
if (hdibCurrent) {
bLegitDraw = TRUE;
lstrcpy(achFileName,"<Clipboard>");
hbiCurrent = hdibCurrent;
if (bMemoryDIB)
hbmCurrent = BitmapFromDib (hdibCurrent, hpalCurrent);
SizeWindow(hWnd);
}
else {
bLegitDraw = FALSE;
ErrMsg("No Memory Available!");
}
}
CloseClipboard ();
}
break;
case IDM_PRINT:
GetWindowText(hWnd, Name, sizeof(Name));
DibInfo(hbiCurrent, &bi);
if (!IsRectEmpty(&rcClip))
{
bi.biWidth = rcClip.right - rcClip.left;
bi.biHeight = rcClip.bottom - rcClip.top;
}
/* Initialise printer stuff */
if (!(hDC = GetPrinterDC()))
break;
xSize = GetDeviceCaps(hDC, HORZRES);
ySize = GetDeviceCaps(hDC, VERTRES);
xRes = GetDeviceCaps(hDC, LOGPIXELSX);
yRes = GetDeviceCaps(hDC, LOGPIXELSY);
/* Use half inch margins on left and right
* and one inch on top. Maintain the same aspect ratio.
*/
dx = xSize - xRes;
dy = (int)((long)dx * bi.biHeight/bi.biWidth);
/* Fix bounding rectangle for the picture .. */
Rect.top = yRes;
Rect.left = xRes / 2;
Rect.bottom = yRes + dy;
Rect.right = xRes / 2 + dx;
/* ... and inform the driver */
Escape(hDC, SET_BOUNDS, sizeof(RECT), (LPSTR)&Rect, NULL);
bSave = TRUE;
if (InitPrinting(hDC, hWnd, hInst, Name)) {
PrintDIB(hWnd, hDC, xRes/2, yRes, dx, dy);
/* Signal to the driver to begin translating the drawing
* commands to printer output...
*/
Escape (hDC, NEWFRAME, NULL, NULL, NULL);
TermPrinting(hDC);
}
DeleteDC(hDC);
break;
case IDM_OPEN:
/* Bring up File/Open ... dialog */
fh = DlgOpenFile (hWnd,
"Select a DIB to display",
(LONG)OF_EXIST | OF_MUSTEXIST | OF_NOOPTIONS,
szBitmapExt,
achFileName,
NULL
);
/* Load up the DIB if the user did not press cancel */
if (fh > 0) {
StartWait();
if (InitDIB (hWnd))
InvalidateRect (hWnd, NULL, FALSE);
else
bLegitDraw = FALSE;
EndWait();
}
break;
case IDM_SAVE:
DibInfo(hbiCurrent,&bi);
fFileOptions = 0;
/* Depending on compression type for current DIB,
* set the appropriate bit in the fFileOptions flag
*/
if (bi.biCompression == BI_RGB)
fFileOptions |= F_RGB;
else if (bi.biCompression == BI_RLE4)
fFileOptions |= F_RLE4;
else if (bi.biCompression == BI_RLE8)
fFileOptions |= F_RLE8;
/* Depending on bits/pixel type for current DIB,
* set the appropriate bit in the fFileOptions flag
*/
switch (bi.biBitCount){
case 1:
fFileOptions |= F_1BPP;
break;
case 4:
fFileOptions |= F_4BPP;
break;
case 8:
fFileOptions |= F_8BPP;
break;
case 24:
fFileOptions |= F_24BPP;
}
/* Bring up File/Save... dialog and get info. about filename,
* compression, and bits/pix. of DIB to be written.
*/
fh = DlgOpenFile (hWnd,
"Select File to save DIB to",
(LONG)OF_EXIST | OF_SAVE | OF_NOSHOWSPEC,
szBitmapExt,
achFileName,
&fFileOptions);
/* Extract DIB specs. if the user did not press cancel */
if (fh != 0){
if (fFileOptions & F_RGB)
bi.biCompression = BI_RGB;
if (fFileOptions & F_RLE4)
bi.biCompression = BI_RLE4;
if (fFileOptions & F_RLE8)
bi.biCompression = BI_RLE8;
if (fFileOptions & F_1BPP)
bi.biBitCount = 1;
if (fFileOptions & F_4BPP)
bi.biBitCount = 4;
if (fFileOptions & F_8BPP)
bi.biBitCount = 8;
if (fFileOptions & F_24BPP)
bi.biBitCount = 24;
/* Realize a DIB in the specified format and obtain a
* handle to it.
*/
hdibCurrent = RealizeDibFormat(bi.biCompression,bi.biBitCount);
if (!hdibCurrent){
ErrMsg("Unable to save the specified file");
return 0L;
}
/* Write the DIB */
StartWait();
if (!WriteDIB(achFileName,hdibCurrent))
ErrMsg("Unable to save the specified file");
EndWait();
}
break;
case IDM_EXIT:
PostMessage(hWnd, WM_SYSCOMMAND, SC_CLOSE, 0L);
break;
case IDM_UPDATECOL:
/* Toggle state of "update screen colors" flag. If it is
* off, clear the "hide changes" flag
*/
bUpdateColors = !bUpdateColors;
if (bUpdateColors)
bNoUgly = 0;
break;
case IDM_DIBSCREEN:
bDIBToDevice = !bDIBToDevice;
InvalidateRect(hWnd, (LPRECT) (NULL), 1);
break;
case IDM_MEMORYDIB:
bMemoryDIB = !bMemoryDIB;
break;
case IDM_NOUGLY:
/* Toggle state of "hide changes" flag. If it is off, clear
* the "update screen colors" flag. This will tell SHOWDIB
* to paint itself black while the palette is changing.
*/
bNoUgly = !bNoUgly;
if (bNoUgly)
bUpdateColors = 0;
break;
case IDM_TRANSPARENT:
/* Toggle DC mode */
wTransparent = wTransparent == TRANSPARENT ?
OPAQUE : TRANSPARENT;
break;
case IDM_ANIMATE0:
if (!hpalSave)
break;
/* Reset animation count and stop timer */
KillTimer(hWnd, 1);
nAnimating = 0;
/* Restore palette which existed before animation started */
DeleteObject(hpalCurrent);
hpalCurrent = hpalSave;
/* Rebuild bitmap based on newly realized information */
hDC = GetDC (hWnd);
SelectPalette (hDC, hpalCurrent, 0);
RealizePalette (hDC);
ReleaseDC (hWnd, hDC);
if (hbmCurrent){
DeleteObject (hbmCurrent);
hbmCurrent = NULL;
if (hdibCurrent)
hbmCurrent = BitmapFromDib (hdibCurrent, hpalCurrent);
}
hpalSave = NULL;
/* Force redraw with new palette for everyone */
InvalidateRect(hWnd, NULL, TRUE);
break;
case IDM_STEALCOL:
case IDM_ANIMATE5:
case IDM_ANIMATE20:
case IDM_ANIMATE50:
case IDM_ANIMATE100:
case IDM_ANIMATE200:
case IDM_ANIMATE201:
/* Set animation count i.e number of times animation is to
* take place.
*/
nAnimating = id;
if (id == IDM_STEALCOL)
nAnimating = 0;
/* Save current palette */
hpalSave = CopyPalette(hpalCurrent);
GetObject(hpalCurrent, sizeof(int), (LPSTR)&pLogPal->palNumEntries);
GetPaletteEntries(hpalCurrent, 0, pLogPal->palNumEntries, pLogPal->palPal
/* Reserve all entries in the palette otherwise AnimatePalette()
* will not modify them
*/
for (i = 0; i < pLogPal->palNumEntries; i++) {
pLogPal->palPalEntry[i].peFlags = (BYTE)PC_RESERVED;
}
SetPaletteEntries(hpalCurrent, 0, pLogPal->palNumEntries, pLogPal->palPal
/* Rebuild bitmap based on newly realized information */
if (hbmCurrent){
DeleteObject (hbmCurrent);
hbmCurrent = NULL;
if (hdibCurrent)
hbmCurrent = BitmapFromDib (hdibCurrent, hpalCurrent);
}
/* Force redraw with new palette for everyone */
InvalidateRect(hWnd, NULL, TRUE);
/* Initiate the timer so that palette can be animated in
* response to a WM_TIMER message
*/
if (nAnimating && !SetTimer(hWnd, 1, 250, (LPSTR) NULL))
nAnimating = 0;
default:
break;
}
return TRUE;
}
/****************************************************************************
* *
* FUNCTION : InitDIB(hWnd) *
* *
* PURPOSE : Reads a DIB from a file, obtains a handle to it's *
* BITMAPINFO struct., sets up the palette and loads the DIB. *
* *
* RETURNS : TRUE - DIB loads ok *
* FALSE - otherwise *
* *
****************************************************************************
int InitDIB(hWnd)
HWND hWnd;
{
unsigned fh;
LPBITMAPINFOHEADER lpbi;
WORD FAR * pw;
int i;
BITMAPINFOHEADER bi;
OFSTRUCT of;
FreeDib();
/* Open the file and get a handle to it's BITMAPINFO */
fh = OpenFile (achFileName, (LPOFSTRUCT)&of, OF_READ);
if (fh == -1) {
ErrMsg("Can't open file '%ls'", (LPSTR)achFileName);
return FALSE;
}
hbiCurrent = ReadDibBitmapInfo(fh);
dwOffset = _llseek(fh, 0L, SEEK_CUR);
_lclose (fh);
if (hbiCurrent == NULL) {
ErrMsg("%ls is not a Legitimate DIB File!", (LPSTR)achFileName);
return FALSE;
}
DibInfo(hbiCurrent,&bi);
/* Set up the palette */
hpalCurrent = CreateDibPalette(hbiCurrent);
if (hpalCurrent == NULL) {
ErrMsg("CreatePalette() Failed");
return FALSE;
}
/* Convert the DIB color table to palette relative indexes, so
* SetDIBits() and SetDIBitsToDevice() can avoid color matching.
* We can do this because the palette we realize is identical
* to the color table of the bitmap, ie the indexes match 1 to 1
*
* Now that the DIB color table is palette indexes not RGB values
* we must use DIB_PAL_COLORS as the wUsage parameter to SetDIBits()
*/
lpbi = (VOID FAR *)GlobalLock(hbiCurrent);
if (lpbi->biBitCount != 24) {
fPalColors = TRUE;
pw = (WORD FAR *)((LPSTR)lpbi + lpbi->biSize);
for (i=0; i<(int)lpbi->biClrUsed; i++)
*pw++ = (WORD)i;
}
GlobalUnlock(hbiCurrent);
bLegitDraw = TRUE;
/* If the input bitmap is not in RGB FORMAT the banding code will
* not work! we need to load the DIB bits into memory.
* if memory DIB, load it all NOW! This will avoid calling the
* banding code.
*/
if (bMemoryDIB || bi.biCompression != BI_RGB)
hdibCurrent = OpenDIB(achFileName);
/* If the RLE could not be loaded all at once, exit gracefully NOW,
* to avoid calling the banding code
*/
if ((bi.biCompression != BI_RGB) && !hdibCurrent){
ErrMsg ("Could not load RLE!");
FreeDib();
return FALSE;
}
if (hdibCurrent && !bDIBToDevice && bMemoryDIB){
hbmCurrent = BitmapFromDib(hdibCurrent,hpalCurrent);
if (!hbmCurrent){
ErrMsg ("Could not create bitmap!");
FreeDib();
return FALSE;
}
}
SizeWindow(hWnd);
return TRUE;
}
/****************************************************************************
* *
* FUNCTION : FreeDib(void) *
* *
* PURPOSE : Frees all currently active bitmap, DIB and palette objects *
* and initializes their handles. *
* *
****************************************************************************
void FreeDib(void)
{
if (hpalCurrent)
DeleteObject(hpalCurrent);
if (hbmCurrent)
DeleteObject(hbmCurrent);
if (hdibCurrent)
GlobalFree(hdibCurrent);
if (hbiCurrent && hbiCurrent != hdibCurrent)
GlobalFree(hbiCurrent);
fPalColors = FALSE;
bLegitDraw = FALSE;
hpalCurrent = NULL;
hdibCurrent = NULL;
hbmCurrent = NULL;
hbiCurrent = NULL;
SetRectEmpty (&rcClip);
}
SHOWFONT.C
CD-ROM Disc Path: \SAMPCODE\WIN_SDK\SHOWFONT\SHOWFONT.C
/****************************************************************************
PROGRAM: Showfont.c
PURPOSE: Adds, deletes, creates and displays fonts
FUNCTIONS:
WinMain() - calls initialization function, processes message loop
EditfileInit() - initializes window data and registers window
EditfileWndProc() - processes messages
About() - processes messages for "About" dialog box
SelectFont() - select a font
GetSizes() - get size of current font
GetFonts() - get available fonts
SetMyDC() - initializes DC
Metric() - Metric dialog box
Log() - Log dialog box
AddDlg() - dialog box for adding a font
RemoveDlg() - dialog box for removing a font
CFontDlg()
_lstrcpy() - long strcpy()
_lstrncpy() - long strncpy()
_lstrlen() - long strlen()
CheckFileName() - check for valid filename
SeparateFile() - Separate filename and pathname
UpdateListBox() - update file list box
AddExt() - add default extension
SetFaceName() - update title with current font's face name
****************************************************************************/
#include "windows.h"
#include "showfont.h"
HANDLE hInst;
HFONT hOFont, hFFont, hVFont, hSFont, hDFont, hMFont, hFont;
int hFile;
char line[4][64];
char FontNameList[32][128]; /* list of added fonts
int nFontIndex = 0; /* position in FontList
int nLineSpace;
TEXTMETRIC TextMetric;
LOGFONT LogFont;
FARPROC lpCFontDlg;
POINT ptCurrent = {0, 0};
short nBkMode = OPAQUE;
DWORD rgbBkColor = RGB(255, 255, 255);
DWORD rgbTextColor = RGB(0, 0, 0);
DWORD rgbColor;
short nAlignLCR = TA_LEFT;
short nAlignTBB = TA_TOP;
WORD wPaint = 0;
FARPROC lpColors;
char FontList[MAXFONT][32];
BYTE CharSet[MAXFONT];
BYTE PitchAndFamily[MAXFONT];
int FontIndex = 0;
int SizeList[MAXSIZE];
int SizeIndex = 0;
int CurrentFont = 0;
int CurrentSize = 0;
FARPROC lpSelectFont;
FARPROC lpEnumFunc;
WORD wPrevVAlign = IDM_ALIGNBASE;
WORD wPrevHAlign = IDM_ALIGNLEFT;
WORD wPrevFont = IDM_SYSTEM;
char AppName[] = "ShowFont Sample Application Font: ";
char WindowTitle[80];
char str[255];
char DefPath[128];
char DefExt[] = ".fon";
char DefSpec[13];
char FontFileName[128];
/****************************************************************************
FUNCTION: WinMain(HANDLE, HANDLE, LPSTR, int)
PURPOSE: calls initialization function, processes message loop
****************************************************************************/
int PASCAL WinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow)
HANDLE hInstance;
HANDLE hPrevInstance;
LPSTR lpCmdLine;
int nCmdShow;
{
HWND hWnd;
MSG msg;
if (!hPrevInstance)
if (!ShowFontInit(hInstance))
return (FALSE);
hInst = hInstance;
strcpy(WindowTitle, AppName);
strcat(WindowTitle, "SYSTEM"); /* default is SYSTEM font
hWnd = CreateWindow("ShowFont",
WindowTitle,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
hInstance,
NULL);
if (!hWnd)
return (FALSE);
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
while (GetMessage(&msg, NULL, NULL, NULL)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (msg.wParam);
}
/****************************************************************************
FUNCTION: ShowFontInit(HANDLE)
PURPOSE: Initializes window data and registers window class
****************************************************************************/
int ShowFontInit(hInstance)
HANDLE hInstance;
{
HANDLE hMemory;
PWNDCLASS pWndClass;
BOOL bSuccess;
hMemory = LocalAlloc(LPTR, sizeof(WNDCLASS));
pWndClass = (PWNDCLASS) LocalLock(hMemory);
pWndClass->hCursor = LoadCursor(NULL, IDC_ARROW);
pWndClass->hIcon = LoadIcon(NULL, IDI_APPLICATION);
pWndClass->lpszMenuName = (LPSTR) "ShowFont";
pWndClass->lpszClassName = (LPSTR) "ShowFont";
pWndClass->hbrBackground = GetStockObject(WHITE_BRUSH);
pWndClass->hInstance = hInstance;
pWndClass->style = NULL;
pWndClass->lpfnWndProc = ShowFontWndProc;
bSuccess = RegisterClass((LPWNDCLASS) pWndClass);
LocalUnlock(hMemory);
LocalFree(hMemory);
return (bSuccess);
}
/****************************************************************************
FUNCTION: SetMyDC(HDC)
PURPOSE: Initializes the DC
****************************************************************************/
HDC SetMyDC(hDC)
HDC hDC;
{
SetBkMode(hDC, nBkMode);
SetBkColor(hDC, rgbBkColor);
SetTextColor(hDC, rgbTextColor);
SetTextAlign(hDC, nAlignLCR | nAlignTBB);
}
/****************************************************************************
FUNCTION: GetStringExtent(HDC, PSTR, HFONT)
PURPOSE: get the string extent
****************************************************************************/
short GetStringExtent(hDC, pString, hFont)
HDC hDC;
PSTR pString;
HFONT hFont;
{
HFONT hOldFont;
DWORD dwExtent;
if (hOldFont=SelectObject(hDC, hFont)) {
dwExtent = GetTextExtent(hDC, pString, strlen(pString));
SelectObject(hDC, hOldFont);
return (LOWORD(dwExtent));
}
else
return (0);
}
/****************************************************************************
FUNCTION: GetStringExtent(HDC, PSTR, HFONT)
PURPOSE: Sends string to application's window
****************************************************************************/
short StringOut(hDC, X, Y, pString, hFont)
HDC hDC;
short X;
short Y;
PSTR pString;
HFONT hFont;
{
HFONT hOldFont;
DWORD dwExtent;
hOldFont = SelectObject(hDC, hFont);
if (hOldFont != NULL) {
dwExtent = GetTextExtent(hDC, pString, strlen(pString));
TextOut(hDC, X, Y, pString, strlen(pString));
SelectObject(hDC, hOldFont);
}
return (LOWORD(dwExtent));
}
/****************************************************************************
FUNCTION: ShowString(HWND)
PURPOSE: Show string in current font
****************************************************************************/
void ShowString(hWnd)
HWND hWnd;
{
HFONT hItalicFont;
HFONT hBoldFont;
HFONT hUnderlineFont;
HFONT hStrikeOutFont;
HDC hDC;
short X, tmpX;
short Y;
short nAlign;
GetObject(hFont, sizeof(LOGFONT), (LPSTR) &LogFont);
LogFont.lfItalic = TRUE;
hItalicFont = CreateFontIndirect(&LogFont);
LogFont.lfItalic = FALSE;
LogFont.lfUnderline = TRUE;
hUnderlineFont = CreateFontIndirect(&LogFont);
LogFont.lfUnderline = FALSE;
LogFont.lfStrikeOut = TRUE;
hStrikeOutFont = CreateFontIndirect(&LogFont);
LogFont.lfStrikeOut = FALSE;
LogFont.lfWeight = FW_BOLD;
hBoldFont = CreateFontIndirect(&LogFont);
hDC=GetDC(hWnd);
SetMyDC(hDC);
X=ptCurrent.x;
Y=ptCurrent.y;
nAlign = nAlignLCR | nAlignTBB; /* GetTextAlign(hDC);
if ((nAlign & TA_CENTER) == TA_CENTER) {
tmpX = X;
nAlignLCR = TA_LEFT;
SetTextAlign(hDC, nAlignLCR | nAlignTBB);
X += StringOut(hDC, X, Y, ", and ", hFont);
X += StringOut(hDC, X, Y, "strikeout", hStrikeOutFont);
X += StringOut(hDC, X, Y, " in a single line.", hFont);
X = tmpX;
nAlignLCR = TA_RIGHT;
SetTextAlign(hDC, nAlignLCR | nAlignTBB);
X -= StringOut(hDC, X, Y, "underline", hUnderlineFont);
X -= StringOut(hDC, X, Y, ", ", hFont);
X -= StringOut(hDC, X, Y, "italic", hItalicFont);
X -= StringOut(hDC, X, Y, ", ", hFont);
X -= StringOut(hDC, X, Y, "bold", hBoldFont);
X -= StringOut(hDC, X, Y, "You can use ", hFont);
nAlignLCR = TA_CENTER;
}
else if ((nAlign & TA_CENTER) == TA_RIGHT) {
X -= StringOut(hDC, X, Y, " in a single line.", hFont);
X -= StringOut(hDC, X, Y, "strikeout", hStrikeOutFont);
X -= StringOut(hDC, X, Y, ", and ", hFont);
X -= StringOut(hDC, X, Y, "underline", hUnderlineFont);
X -= StringOut(hDC, X, Y, ", ", hFont);
X -= StringOut(hDC, X, Y, "italic", hItalicFont);
X -= StringOut(hDC, X, Y, ", ", hFont);
X -= StringOut(hDC, X, Y, "bold", hBoldFont);
X -= StringOut(hDC, X, Y, "You can use ", hFont);
}
else {
X += StringOut(hDC, X, Y, "You can use ", hFont);
X += StringOut(hDC, X, Y, "bold", hBoldFont);
X += StringOut(hDC, X, Y, ", ", hFont);
X += StringOut(hDC, X, Y, "italic", hItalicFont);
X += StringOut(hDC, X, Y, ", ", hFont);
X += StringOut(hDC, X, Y, "underline", hUnderlineFont);
X += StringOut(hDC, X, Y, ", and ", hFont);
X += StringOut(hDC, X, Y, "strikeout", hStrikeOutFont);
X += StringOut(hDC, X, Y, " in a single line.", hFont);
}
ReleaseDC(hWnd, hDC);
DeleteObject(hItalicFont);
DeleteObject(hUnderlineFont);
DeleteObject(hStrikeOutFont);
DeleteObject(hBoldFont);
}
/****************************************************************************
FUNCTION: ShowCharacterSet(HDC, HFONT)
PURPOSE: display character set using current font
****************************************************************************/
void ShowCharacterSet(hDC, hFont)
HDC hDC;
HFONT hFont;
{
HFONT hOldFont;
TEXTMETRIC TextMetric;
int LineSpace;
short X;
short Y;
if (!(hOldFont = SelectObject(hDC, hFont)))
return;
GetTextMetrics(hDC, &TextMetric);
nLineSpace = (TextMetric.tmHeight + TextMetric.tmExternalLeading)*2;
X = ptCurrent.x;
Y = ptCurrent.y;
TextOut(hDC, X, Y, line[0], 64);
TextOut(hDC, X, Y += nLineSpace, line[1], 64);
TextOut(hDC, X, Y += nLineSpace, line[2], 64);
TextOut(hDC, X, Y += nLineSpace, line[3], 64);
SelectObject(hDC, hOldFont);
}
/****************************************************************************
FUNCTION: ShowLogFont(HWND, HFONT)
PURPOSE: Create dialog box to show information about logical font
****************************************************************************/
void ShowLogFont(hWnd, hFont)
HWND hWnd;
HFONT hFont;
{
HFONT hOldFont;
FARPROC lpProcLog;
HDC hDC;
TEXTMETRIC TextMetric;
HANDLE hDlgBox;
char buf[80];
char DialogTitle[100];
hDC = GetDC(hWnd);
if (!(hOldFont = SelectObject(hDC, hSFont)))
return;
GetTextMetrics(hDC, &TextMetric);
nLineSpace = TextMetric.tmHeight + TextMetric.tmExternalLeading;
GetObject(hFont, sizeof(LOGFONT), (LPSTR) &LogFont);
lpProcLog = MakeProcInstance((FARPROC) Log, hInst);
hDlgBox = CreateDialog(hInst, "LogBox", hWnd, lpProcLog);
strcpy(DialogTitle, "Log Font: ");
strcat(DialogTitle, LogFont.lfFaceName);
SetWindowText(hDlgBox, (LPSTR) DialogTitle);
SelectObject(hDC, hOldFont);
ReleaseDC(hWnd, hDC);
}
/****************************************************************************
FUNCTION: ShowMetricFont(HWND, HFONT)
PURPOSE: Create dialog box to show information about metric font
****************************************************************************/
void ShowTextMetric(hWnd, hFont)
HWND hWnd;
HFONT hFont;
{
FARPROC lpProcMetric;
HFONT hOldFont;
TEXTMETRIC LocalTextMetric;
HDC hDC;
HANDLE hDlgBox;
char buf[80];
char DialogTitle[100];
hDC = GetDC(hWnd);
if (!(hOldFont = SelectObject(hDC, hFont)))
return;
GetTextMetrics(hDC, &TextMetric);
lpProcMetric = MakeProcInstance((FARPROC) Metric, hInst);
hDlgBox = CreateDialog(hInst, "MetricBox", hWnd, lpProcMetric);
strcpy(DialogTitle, "Metric Font: ");
GetTextFace(hDC, 80, buf);
strcat(DialogTitle, buf);
SetWindowText(hDlgBox, (LPSTR) DialogTitle);
SelectObject(hDC, hOldFont);
ReleaseDC(hWnd, hDC);
}
/****************************************************************************
FUNCTION: Colors(HWND, unsigned, WORD LONG)
PURPOSE: Dialog box for changing background color of text
****************************************************************************/
BOOL FAR PASCAL Colors(hDlg, message, wParam, lParam)
HWND hDlg;
unsigned message;
WORD wParam;
LONG lParam;
{
int Red, Green, Blue;
switch (message) {
case WM_INITDIALOG:
SetDlgItemInt(hDlg, ID_RED, GetRValue(rgbColor), FALSE);
SetDlgItemInt(hDlg, ID_GREEN, GetGValue(rgbColor), FALSE);
SetDlgItemInt(hDlg, ID_BLUE, GetBValue(rgbColor), FALSE);
return (TRUE);
break;
case WM_COMMAND:
switch (wParam) {
case IDOK:
Red = GetDlgItemInt(hDlg, ID_RED, NULL, FALSE);
Green = GetDlgItemInt(hDlg, ID_GREEN, NULL, FALSE);
Blue = GetDlgItemInt(hDlg, ID_BLUE, NULL, FALSE);
rgbColor = RGB(Red, Green, Blue);
EndDialog(hDlg, 1);
break;
case IDCANCEL:
EndDialog(hDlg, 0);
break;
}
break;
}
return (FALSE);
}
/****************************************************************************
FUNCTION: EnumFunc(LPLOGFONT, LPTEXTMETRIC, short, LPSTR)
PURPOSE: Initializes window data and registers window class
****************************************************************************/
int FAR PASCAL EnumFunc(lpLogFont, lpTextMetric, FontType, lpData)
LPLOGFONT lpLogFont;
LPTEXTMETRIC lpTextMetric;
short FontType;
LPSTR lpData;
{
switch (LOWORD(lpData)) {
case 0:
if (FontIndex >= MAXFONT)
return (0);
_lstrcpy((LPSTR) FontList[FontIndex],
(LPSTR) (lpLogFont->lfFaceName));
CharSet[FontIndex] = lpLogFont->lfCharSet;
PitchAndFamily[FontIndex] = lpLogFont->lfPitchAndFamily;
return (++FontIndex);
case 1:
if (SizeIndex >= MAXSIZE)
return (0);
SizeList[SizeIndex] = lpLogFont->lfHeight;
return (++SizeIndex);
}
}
/****************************************************************************
FUNCTION: GetFonts(HWND)
PURPOSE: Get available fonts
****************************************************************************/
void GetFonts(hWnd)
HWND hWnd;
{
HDC hDC;
FontIndex = 0;
SizeIndex = 0;
hDC = GetDC(hWnd);
lpEnumFunc = MakeProcInstance(EnumFunc, hInst);
EnumFonts(hDC, (LPSTR) NULL, lpEnumFunc, (LPSTR) NULL);
FreeProcInstance(lpEnumFunc);
ReleaseDC(hWnd, hDC);
}
/****************************************************************************
FUNCTION: GetSizes(hWnd, CurrentFont)
PURPOSE: Get size of current font
****************************************************************************/
void GetSizes(hWnd, CurrentFont)
HWND hWnd;
int CurrentFont;
{
HDC hDC;
SizeIndex = 0;
hDC = GetDC(hWnd);
lpEnumFunc = MakeProcInstance(EnumFunc, hInst);
EnumFonts(hDC, FontList[CurrentFont], lpEnumFunc, (LPSTR) 1L);
FreeProcInstance(lpEnumFunc);
ReleaseDC(hWnd, hDC);
}
/****************************************************************************
FUNCTION: SelectFont(HWND, unsigned, WORD, LONG)
PURPOSE: Initializes window data and registers window class
****************************************************************************/
BOOL FAR PASCAL SelectFont(hDlg, message, wParam, lParam)
HWND hDlg;
unsigned message;
WORD wParam;
LONG lParam;
{
int i;
int index;
char buf[LF_FACESIZE];
switch (message) {
case WM_INITDIALOG:
for (i=0; i<FontIndex; i++) { /* displays available fonts
SendDlgItemMessage(hDlg, ID_TYPEFACE, LB_ADDSTRING,
NULL, (LONG) (LPSTR) FontList[i]);
SendDlgItemMessage(hDlg, ID_TYPEFACE, LB_SETCURSEL,
0, 0L);
}
GetSizes(hDlg, 0);
for (i=0; i<SizeIndex; i++) { /* displays font sizes
sprintf(buf, "%d", SizeList[i]);
SendDlgItemMessage(hDlg, ID_SIZE, LB_ADDSTRING,
0, (LONG) (LPSTR) buf);
SendDlgItemMessage(hDlg, ID_SIZE, LB_SETCURSEL,
0, 0L);
}
return (TRUE);
break;
case WM_COMMAND:
switch (wParam) {
case IDOK:
okay:
index=SendDlgItemMessage(hDlg, ID_TYPEFACE,
LB_GETCURSEL, 0, 0L);
if (index == LB_ERR) {
MessageBox(hDlg, "No font selected",
"Select Font", MB_OK | MB_ICONEXCLAMATION);
break;
}
CurrentFont = index;
index = SendDlgItemMessage(hDlg, ID_SIZE,
LB_GETCURSEL, 0, 0L);
if (index == LB_ERR) {
MessageBox(hDlg, "No size selected",
"Select Font", MB_OK | MB_ICONEXCLAMATION);
break;
}
CurrentSize = index;
EndDialog(hDlg, 1);
break;
case IDCANCEL:
EndDialog(hDlg, 0);
break;
case ID_TYPEFACE:
switch (HIWORD(lParam)) {
case LBN_SELCHANGE:
index = SendDlgItemMessage(hDlg, ID_TYPEFACE,
LB_GETCURSEL, 0, 0L);
if (index == LB_ERR)
break;
SendDlgItemMessage(hDlg, ID_SIZE, LB_RESETCONTENT, 0, 0L)
GetSizes(hDlg, index);
for (i = 0; i < SizeIndex; i++) {
sprintf(buf, "%d", SizeList[i]);
SendDlgItemMessage(hDlg, ID_SIZE,
LB_ADDSTRING, 0, (LONG) (LPSTR) buf);
SendDlgItemMessage(hDlg, ID_SIZE, LB_SETCURSEL, 0, 0L
}
break;
case LBN_DBLCLK:
goto okay;
break;
}
break;
case ID_SIZE:
if(HIWORD(lParam) == LBN_DBLCLK)
goto okay;
break;
}
break;
}
return (FALSE);
}
/****************************************************************************
FUNCTION: ShowFontWndProc(HWND, unsigned, WORD, LONG)
PURPOSE: Processes messages
****************************************************************************/
long FAR PASCAL ShowFontWndProc(hWnd, message, wParam, lParam)
HWND hWnd;
unsigned message;
WORD wParam;
LONG lParam;
{
FARPROC lpProcAbout, lpAddDlg, lpRemoveDlg;
HDC hDC;
PAINTSTRUCT ps;
HFONT hOldFont;
int i;
short Y;
char buf[80];
switch(message) {
case WM_CREATE:
GetFonts(hWnd);
hMFont = CreateFont(
10, /* height
10, /* width
0, /* escapement
0, /* orientation
FW_NORMAL, /* weight
FALSE, /* italic
FALSE, /* underline
FALSE, /* strikeout
OEM_CHARSET, /* charset
OUT_DEFAULT_PRECIS, /* out precision
CLIP_DEFAULT_PRECIS, /* clip precision
DEFAULT_QUALITY, /* quality
FIXED_PITCH | FF_MODERN, /* pitch and family
"Courier"); /* typeface
hOFont = GetStockObject(OEM_FIXED_FONT);
hFFont = GetStockObject(ANSI_FIXED_FONT);
hVFont = GetStockObject(ANSI_VAR_FONT);
hSFont = GetStockObject(SYSTEM_FONT);
hDFont = GetStockObject(DEVICE_DEFAULT_FONT);
hFont = hSFont;
GetObject(hFont, sizeof(LOGFONT), (LPSTR) &LogFont);
strcpy(WindowTitle, AppName);
strcat(WindowTitle, "SYSTEM");
SetWindowText(hWnd, (LPSTR) WindowTitle);
for (i=0; i<64; i++) {
line[0][i] = i;
line[1][i] = i+64;
line[2][i] = i+128;
line[3][i] = i+192;
}
break;
case WM_PAINT:
hDC = BeginPaint(hWnd, &ps);
SetMyDC(hDC);
switch (wPaint) {
case IDM_SHOWCHARSET:
ShowCharacterSet(hDC, hFont);
break;
}
EndPaint(hWnd, &ps);
break;
case WM_COMMAND:
switch (wParam) {
/* File menu */
case IDM_ADDFONT:
/* Call AddDlg() to get the filename */
lpAddDlg = MakeProcInstance((FARPROC) AddDlg, hInst);
if (DialogBox(hInst, "Add", hWnd, lpAddDlg)) {
/* Check to see if it is a new font name */
for (i = 0; i < nFontIndex; i++) {
if (!strcmp(FontFileName, &FontNameList[i][0])) {
MessageBox(hWnd, "Font already exists",
"Add Font", MB_OK | MB_ICONQUESTION);
FreeProcInstance(lpAddDlg);
return (0L);
}
}
/* Tell Windows to add the font resource */
AddFontResource((LPSTR) FontFileName);
/* Let all applications know there is a new font
* resource
*/
SendMessage((HWND) 0xFFFF, WM_FONTCHANGE, NULL,
(LONG) NULL);
/* Copy the name selected to the list of fonts added
strcpy(&FontNameList[nFontIndex++][0], FontFileName);
}
FreeProcInstance(lpAddDlg);
break;
case IDM_DELFONT:
if (!nFontIndex) {
MessageBox(hWnd, "No fonts to delete",
"Remove Font", MB_OK | MB_ICONQUESTION);
break;
}
lpRemoveDlg = MakeProcInstance((FARPROC) RemoveDlg, hInst
if (DialogBox(hInst, "Remove", hWnd, lpRemoveDlg)) {
for (i = 0; i < nFontIndex; i++) {
if (!strcmp(FontFileName, &FontNameList[i][0])) {
RemoveFontResource((LPSTR) FontFileName);
SendMessage((HWND) 0xFFFF, WM_FONTCHANGE, NUL
(LONG) NULL);
strcpy(&FontNameList[i][0],
&FontNameList[--nFontIndex][0]);
break;
}
}
}
FreeProcInstance(lpRemoveDlg);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
case IDM_ABOUT:
lpProcAbout = MakeProcInstance((FARPROC) About, hInst);
DialogBox(hInst, "AboutBox", hWnd, lpProcAbout);
FreeProcInstance(lpProcAbout);
break;
/* Show menu */
case IDM_SHOWSTRING:
ShowString(hWnd);
break;
case IDM_SHOWCHARSET:
InvalidateRect(hWnd, (LPRECT)NULL, TRUE);
wPaint = wParam;
break;
case IDM_SHOWLOGFONT:
ShowLogFont(hWnd, hFont);
break;
case IDM_SHOWTEXTMETRICS:
ShowTextMetric(hWnd, hFont);
break;
case IDM_CLEAR:
InvalidateRect(hWnd, (LPRECT)NULL, TRUE);
wPaint = 0;
break;
/* Font menu */
case IDM_OEM:
hFont = hOFont;
SetFaceName(hWnd); /* sets window title
CheckMenuItem(GetMenu(hWnd), wPrevFont, MF_UNCHECKED);
CheckMenuItem(GetMenu(hWnd), wParam, MF_CHECKED);
wPrevFont = wParam;
break;
case IDM_ANSIFIXED:
hFont = hFFont;
SetFaceName(hWnd);
CheckMenuItem(GetMenu(hWnd), wPrevFont, MF_UNCHECKED);
CheckMenuItem(GetMenu(hWnd), wParam, MF_CHECKED);
wPrevFont = wParam;
break;
case IDM_ANSIVAR:
hFont = hVFont;
SetFaceName(hWnd);
CheckMenuItem(GetMenu(hWnd), wPrevFont, MF_UNCHECKED);
CheckMenuItem(GetMenu(hWnd), wParam, MF_CHECKED);
wPrevFont = wParam;
break;
case IDM_SYSTEM:
hFont = hSFont;
SetFaceName(hWnd);
CheckMenuItem(GetMenu(hWnd), wPrevFont, MF_UNCHECKED);
CheckMenuItem(GetMenu(hWnd), wParam, MF_CHECKED);
wPrevFont = wParam;
break;
case IDM_DEVICEDEF:
hFont = hDFont;
SetFaceName(hWnd);
CheckMenuItem(GetMenu(hWnd), wPrevFont, MF_UNCHECKED);
CheckMenuItem(GetMenu(hWnd), wParam, MF_CHECKED);
wPrevFont = wParam;
break;
case IDM_SELECTFONT:
lpSelectFont = MakeProcInstance(SelectFont, hInst);
if (DialogBox(hInst, "SelectFont", hWnd, lpSelectFont)) {
DeleteObject(hMFont);
hMFont = CreateFont(
SizeList[CurrentSize],
0,
0,
0,
FW_NORMAL,
FALSE,
FALSE,
FALSE,
CharSet[CurrentFont],
OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS,
DEFAULT_QUALITY,
PitchAndFamily[CurrentFont],
FontList[CurrentFont]);
hFont = hMFont;
SetFaceName(hWnd);
}
FreeProcInstance(lpSelectFont);
break;
case IDM_CFONT:
lpCFontDlg = MakeProcInstance(CFontDlg, hInst);
GetObject(hMFont, sizeof(LOGFONT), (LPSTR) &CLogFont);
if (DialogBox(hInst, "CFont", hWnd, lpCFontDlg)) {
DeleteObject(hMFont);
hMFont = CreateFontIndirect(&CLogFont);
hFont = hMFont;
SetFaceName(hWnd);
}
FreeProcInstance(lpCFontDlg);
break;
/* Options menu */
case IDM_TEXTCOLOR:
lpColors = MakeProcInstance(Colors, hInst);
rgbColor = rgbTextColor;
if (DialogBox(hInst, "Colors", hWnd, lpColors))
rgbTextColor = rgbColor;
FreeProcInstance(lpColors);
break;
case IDM_BACKGROUNDCOLOR:
lpColors = MakeProcInstance(Colors, hInst);
rgbColor = rgbBkColor;
if (DialogBox(hInst, "Colors", hWnd, lpColors))
rgbBkColor = rgbColor;
FreeProcInstance(lpColors);
break;
case IDM_OPAQUE:
nBkMode = OPAQUE;
CheckMenuItem(GetMenu(hWnd), IDM_TRANSPARENT, MF_UNCHECKE
CheckMenuItem(GetMenu(hWnd), IDM_OPAQUE, MF_CHECKED);
break;
case IDM_TRANSPARENT:
nBkMode = TRANSPARENT;
CheckMenuItem(GetMenu(hWnd), IDM_OPAQUE, MF_UNCHECKED);
CheckMenuItem(GetMenu(hWnd), IDM_TRANSPARENT, MF_CHECKED
break;
case IDM_ALIGNLEFT:
nAlignLCR = TA_LEFT;
CheckMenuItem(GetMenu(hWnd), wPrevHAlign, MF_UNCHECKED);
CheckMenuItem(GetMenu(hWnd), wParam, MF_CHECKED);
wPrevHAlign = wParam;
break;
case IDM_ALIGNCENTER:
nAlignLCR = TA_CENTER;
CheckMenuItem(GetMenu(hWnd), wPrevHAlign, MF_UNCHECKED);
CheckMenuItem(GetMenu(hWnd), wParam, MF_CHECKED);
wPrevHAlign = wParam;
break;
case IDM_ALIGNRIGHT:
nAlignLCR = TA_RIGHT;
CheckMenuItem(GetMenu(hWnd), wPrevHAlign, MF_UNCHECKED);
CheckMenuItem(GetMenu(hWnd), wParam, MF_CHECKED);
wPrevHAlign = wParam;
break;
case IDM_ALIGNTOP:
nAlignTBB = TA_TOP;
CheckMenuItem(GetMenu(hWnd), wPrevVAlign, MF_UNCHECKED);
CheckMenuItem(GetMenu(hWnd), wParam, MF_CHECKED);
wPrevVAlign = wParam;
break;
case IDM_ALIGNBASE:
nAlignTBB = TA_BASELINE;
CheckMenuItem(GetMenu(hWnd), wPrevVAlign, MF_UNCHECKED);
CheckMenuItem(GetMenu(hWnd), wParam, MF_CHECKED);
wPrevVAlign = wParam;
break;
case IDM_ALIGNBOTTOM:
nAlignTBB = TA_BOTTOM;
CheckMenuItem(GetMenu(hWnd), wPrevVAlign, MF_UNCHECKED);
CheckMenuItem(GetMenu(hWnd), wParam, MF_CHECKED);
wPrevVAlign = wParam;
break;
}
break;
case WM_LBUTTONUP:
ptCurrent.x = LOWORD(lParam);
ptCurrent.y = HIWORD(lParam);
ShowString(hWnd);
break;
case WM_FONTCHANGE:
GetFonts(hWnd);
break;
case WM_DESTROY:
/* Remove any fonts that were added */
for (i = 0; i < nFontIndex; i++)
RemoveFontResource((LPSTR) &FontNameList[i][0]);
/* Notify any other applications know the fonts have been deleted
SendMessage((HWND) 0xFFFF, WM_FONTCHANGE, NULL, (LONG) NULL);
PostQuitMessage(0);
break;
default:
return (DefWindowProc(hWnd, message, wParam, lParam));
}
return (0L);
}
/****************************************************************************
FUNCTION: Metric(HWND, unsigned, WORD, LONG)
PURPOSE: Modeless dialog box to display metric font information
****************************************************************************/
BOOL FAR PASCAL Metric(hDlg, message, wParam, lParam)
HWND hDlg;
unsigned message;
WORD wParam;
LONG lParam;
{
switch (message) {
case WM_INITDIALOG:
SetDlgItemInt(hDlg, IDMB_HEIGHT, TextMetric.tmHeight, FALSE);
SetDlgItemInt(hDlg, IDMB_ASCENT, TextMetric.tmAscent, FALSE);
SetDlgItemInt(hDlg, IDMB_DESCENT, TextMetric.tmDescent, FALSE);
SetDlgItemInt(hDlg, IDMB_INTERNALLEADING,
TextMetric.tmInternalLeading, FALSE);
SetDlgItemInt(hDlg, IDMB_EXTERNALLEADING,
TextMetric.tmExternalLeading, FALSE);
SetDlgItemInt(hDlg, IDMB_AVECHARWIDTH, TextMetric.tmAveCharWidth,
FALSE);
SetDlgItemInt(hDlg, IDMB_MAXCHARWIDTH, TextMetric.tmMaxCharWidth,
FALSE);
SetDlgItemInt(hDlg, IDMB_WEIGHT, TextMetric.tmWeight, FALSE);
SetDlgItemInt(hDlg, IDMB_ITALIC, TextMetric.tmItalic, FALSE);
SetDlgItemInt(hDlg, IDMB_UNDERLINED, TextMetric.tmUnderlined,
FALSE);
SetDlgItemInt(hDlg, IDMB_STRUCKOUT, TextMetric.tmStruckOut, FALSE
SetDlgItemInt(hDlg, IDMB_FIRSTCHAR, TextMetric.tmFirstChar, FALSE
SetDlgItemInt(hDlg, IDMB_LASTCHAR, TextMetric.tmLastChar, FALSE);
SetDlgItemInt(hDlg, IDMB_DEFAULTCHAR, TextMetric.tmDefaultChar,
FALSE);
SetDlgItemInt(hDlg, IDMB_BREAKCHAR, TextMetric.tmBreakChar, FALSE
SetDlgItemInt(hDlg, IDMB_PITCHANDFAMILY,
TextMetric.tmPitchAndFamily, FALSE);
SetDlgItemInt(hDlg, IDMB_CHARSET, TextMetric.tmCharSet, FALSE);
SetDlgItemInt(hDlg, IDMB_OVERHANG, TextMetric.tmOverhang, FALSE);
SetDlgItemInt(hDlg, IDMB_DIGITIZEDASPECTX,
TextMetric.tmDigitizedAspectX, FALSE);
SetDlgItemInt(hDlg, IDMB_DIGITIZEDASPECTY,
TextMetric.tmDigitizedAspectY, FALSE);
return (TRUE);
case WM_CLOSE:
DestroyWindow(hDlg);
break;
}
return (FALSE);
}
/****************************************************************************
FUNCTION: Log(HWND, unsigned, WORD, LONG)
PURPOSE: Displays logical font information
****************************************************************************/
BOOL FAR PASCAL Log(hDlg, message, wParam, lParam)
HWND hDlg;
unsigned message;
WORD wParam;
LONG lParam;
{
switch (message) {
case WM_INITDIALOG:
SetDlgItemInt(hDlg, IDMI_HEIGHT, LogFont.lfHeight, FALSE);
SetDlgItemInt(hDlg, IDMI_WIDTH, LogFont.lfWidth, FALSE);
SetDlgItemInt(hDlg, IDMI_ESCAPEMENT, LogFont.lfEscapement, FALSE)
SetDlgItemInt(hDlg, IDMI_ORIENTATION, LogFont.lfOrientation, FALS
SetDlgItemInt(hDlg, IDMI_WEIGHT, LogFont.lfWeight, FALSE);
SetDlgItemInt(hDlg, IDMI_ITALIC, LogFont.lfItalic, FALSE);
SetDlgItemInt(hDlg, IDMI_UNDERLINED, LogFont.lfUnderline, FALSE);
SetDlgItemInt(hDlg, IDMI_STRIKEOUT, LogFont.lfStrikeOut, FALSE);
SetDlgItemInt(hDlg, IDMI_CHARSET, LogFont.lfCharSet, FALSE);
SetDlgItemInt(hDlg, IDMI_OUTPRECISION, LogFont.lfOutPrecision,
FALSE);
SetDlgItemInt(hDlg, IDMI_CLIPPRECISION, LogFont.lfClipPrecision,
FALSE);
SetDlgItemInt(hDlg, IDMI_QUALITY, LogFont.lfQuality, FALSE);
SetDlgItemInt(hDlg, IDMI_PITCHANDFAMILY,
LogFont.lfPitchAndFamily, FALSE);
return (TRUE);
case WM_CLOSE:
DestroyWindow(hDlg);
break;
}
return (FALSE);
}
/****************************************************************************
FUNCTION: AddDlg(HWND, unsigned, WORD, LONG)
PURPOSE: Used to add a font
COMMENTS:
This dialog box displays all the availble font files on the currently
selected directory, and lets the user select a font to add.
****************************************************************************/
BOOL FAR PASCAL AddDlg(hDlg, message, wParam, lParam)
HWND hDlg;
unsigned message;
WORD wParam;
LONG lParam;
{
switch (message) {
case WM_COMMAND:
switch (wParam) {
case ID_LISTBOX:
switch (HIWORD(lParam)) {
case LBN_SELCHANGE:
/* If item is a directory name, append "*.*" */
if (DlgDirSelect(hDlg, str, ID_LISTBOX))
strcat(str, DefSpec);
SetDlgItemText(hDlg, ID_EDIT, str);
SendDlgItemMessage(hDlg,
ID_EDIT,
EM_SETSEL,
NULL,
MAKELONG(0, 0x7fff));
break;
case LBN_DBLCLK:
goto CheckSelection;
break;
} /* end of ID_LISTBOX case
return (TRUE);
case IDOK:
CheckSelection:
/* Get the filename from the edit control */
GetDlgItemText(hDlg, ID_EDIT, str, 128);
GetDlgItemText(hDlg, ID_PATH, DefPath, 128);
/* Check for wildcard. If found, use the string as a new
* search path.
*/
if (strchr(str, '*') ||
strchr(str, '?')) {
/* Separate filename from path. The path is stored in
* str which is discarded if null, else it is used for a
* search path.
*/
SeparateFile(hDlg, (LPSTR) str, (LPSTR) DefSpec,
(LPSTR) str);
if (str[0])
strcpy(DefPath, str);
UpdateListBox(hDlg);
return (TRUE);
}
/* Ignore it if no filename specified */
if (!str[0]) {
MessageBox(hDlg, "No filename specified.",
NULL, MB_OK | MB_ICONQUESTION);
return (TRUE);
}
/* Append the default extension if needed */
strcpy(FontFileName, DefPath);
strcat(FontFileName, str);
AddExt(FontFileName, DefExt);
EndDialog(hDlg, TRUE);
return (TRUE);
case IDCANCEL:
/* Let the caller know the user cancelled */
EndDialog(hDlg, FALSE);
return (TRUE);
}
break;
case WM_INITDIALOG:
SetWindowText(hDlg, (LPSTR) "Add Font Resource");
strcpy(DefSpec, "*.fon");
UpdateListBox(hDlg);
SetDlgItemText(hDlg, ID_EDIT, DefSpec);
SendDlgItemMessage(hDlg, ID_EDIT, EM_SETSEL, NULL,
MAKELONG(0, 0x7fff));
SetFocus(GetDlgItem(hDlg, ID_EDIT));
return (FALSE);
}
return FALSE;
}
/****************************************************************************
FUNCTION: RemoveDlg(HANDLE)
PURPOSE: Used to remove a font
COMMENTS:
This dialog box displays all fonts which have been added to the syste
and lets the user select which font to delete.
****************************************************************************/
BOOL FAR PASCAL RemoveDlg(hDlg, message, wParam, lParam)
HWND hDlg;
unsigned message;
WORD wParam;
LONG lParam;
{
WORD index;
int i;
switch (message) {
case WM_COMMAND:
switch (wParam) {
case ID_LISTBOX:
switch (HIWORD(lParam)) {
case LBN_SELCHANGE:
index = SendDlgItemMessage(hDlg,
ID_LISTBOX,
LB_GETCURSEL, /* get index command
NULL,
(LONG) NULL);
SendDlgItemMessage(hDlg,
ID_LISTBOX,
LB_GETTEXT, /* copy string command
index,
(LONG) (LPSTR) FontFileName);
SetDlgItemText(hDlg, ID_EDIT, FontFileName);
break;
case LBN_DBLCLK:
GetDlgItemText(hDlg, ID_EDIT, FontFileName, 128);
EndDialog(hDlg, TRUE);
return (TRUE);
}
return (TRUE);
case IDOK:
/* Get the filename from the edit control */
GetDlgItemText(hDlg, ID_EDIT, FontFileName, 128);
/* Ignore it if no filename specified */
if (!FontFileName[0]) {
MessageBox(hDlg, "No filename specified.",
NULL, MB_OK | MB_ICONQUESTION);
return (TRUE);
}
EndDialog(hDlg, TRUE);
return (TRUE);
case IDCANCEL:
EndDialog(hDlg, FALSE);
return (TRUE);
}
break;
case WM_INITDIALOG:
SetWindowText(hDlg, (LPSTR) "Remove Font Resource");
for (i = 0; i < nFontIndex; i++)
SendDlgItemMessage(hDlg,
ID_LISTBOX,
LB_ADDSTRING,
NULL,
(LONG)(char far *) &FontNameList[i][0]);
SetFocus(GetDlgItem(hDlg, ID_EDIT));
return (FALSE);
}
return FALSE;
}
/****************************************************************************
FUNCTION: UpdateListBox(HWND);
PURPOSE: Update the list box of OpenDlg
****************************************************************************/
void UpdateListBox(hDlg)
HWND hDlg;
{
strcpy(str, DefPath);
strcat(str, DefSpec);
DlgDirList(hDlg, str, ID_LISTBOX, ID_PATH, 0x4010);
SetDlgItemText(hDlg, ID_EDIT, DefSpec);
}
/****************************************************************************
FUNCTION: AddExt(PSTR, PSTR);
PURPOSE: Add default extension
/***************************************************************************/
void AddExt(Name, Ext)
PSTR Name, Ext;
{
PSTR pTptr;
pTptr = Name;
while (*pTptr && *pTptr != '.')
pTptr++;
if (*pTptr != '.')
strcat(Name, Ext);
}
/****************************************************************************
FUNCTION: SeparateFile(HWND, LPSTR, LPSTR, LPSTR)
PURPOSE: Separate filename and pathname
COMMENTS:
This function takes a source filespec and splits it into a path and a
filename, and copies these into the strings specified. Because it
uses the AnsiPrev call, it will work in any language.
****************************************************************************/
void SeparateFile(hDlg, lpDestPath, lpDestFileName, lpSrcFileName)
HWND hDlg;
LPSTR lpDestPath, lpDestFileName, lpSrcFileName;
{
LPSTR lpTmp;
lpTmp = lpSrcFileName + (long) _lstrlen(lpSrcFileName);
while (*lpTmp != ':' && *lpTmp != '\\' && lpTmp > lpSrcFileName)
lpTmp = AnsiPrev(lpSrcFileName, lpTmp);
if (*lpTmp != ':' && *lpTmp != '\\') { /* no path given
_lstrcpy(lpDestFileName, lpSrcFileName);
lpDestPath[0] = 0;
return;
}
_lstrcpy(lpDestFileName, lpTmp + 1L);
_lstrncpy(lpDestPath, lpSrcFileName, (int) (lpTmp - lpSrcFileName) + 1);
lpDestPath[(lpTmp - lpSrcFileName) + 1] = 0;
}
/****************************************************************************
FUNCTION: _lstrlen(LPSTR)
PURPOSE: uses a long far pointer to the string, returns the length
****************************************************************************/
int _lstrlen(lpStr)
LPSTR lpStr;
{
int i;
for (i=0; *lpStr++; i++);
return (i);
}
/****************************************************************************
FUNCTION: _lstrncpy(LPSTR, LPSTR)
PURPOSE: FAR version of strncpy()
****************************************************************************/
void _lstrncpy(lpDest, lpSrc, n)
LPSTR lpDest, lpSrc;
int n;
{
while (n--)
if(!(*lpDest++ = *lpSrc++))
return;
}
/****************************************************************************
FUNCTION: _lstrcpy(LPSTR, LPSTR)
PURPOSE: FAR version of strcpy()
****************************************************************************/
void _lstrcpy(lpDest, lpSrc)
LPSTR lpDest, lpSrc;
{
while(*lpDest++ = *lpSrc++);
}
/****************************************************************************
FUNCTION: SetFaceName(HWND)
PURPOSE: Retireves current font's face name, places it in WindowTitle
****************************************************************************/
SetFaceName(hWnd)
HWND hWnd;
{
char buf[80];
HDC hDC;
hDC = GetDC(hWnd);
SelectObject(hDC, hFont);
strcpy(WindowTitle, AppName);
GetTextFace(hDC, 80, buf);
strcat(WindowTitle, buf);
SetWindowText(hWnd, (LPSTR) WindowTitle);
ReleaseDC(hWnd, hDC);
}
/****************************************************************************
FUNCTION: About(HWND, unsigned, WORD, LONG)
PURPOSE: Processes messages for "About" dialog box
MESSAGES:
WM_INITDIALOG - initialize dialog box
WM_COMMAND - Input received
****************************************************************************/
BOOL FAR PASCAL About(hDlg, message, wParam, lParam)
HWND hDlg;
unsigned message;
WORD wParam;
LONG lParam;
{
switch (message) {
case WM_INITDIALOG:
return (TRUE);
case WM_COMMAND:
if (wParam == IDOK) {
EndDialog(hDlg, TRUE);
return (TRUE);
}
return (TRUE);
}
return (FALSE);
}
TTY.C
CD-ROM Disc Path: \SAMPCODE\WIN_SDK\TTY\TTY.C
//
// FILE: TTY.c
// PURPOSE: This sample terminal application demonstrates
// the basic uses of Windows Communications functions.
// It also shows the basic structure for a terminal program.
// FUNCTIONS:
// WinMain() - Initializes app, calls all other functions.
// TTYWndProc() - Window procedure for terminal window.
// About() - Window procedure for About dialog box.
// AboutInit() - Initialization procedure for About dialog box.
// SettingDlgProc() - Window procedure for Comm Settings dialog.
//
#include <windows.h>
#include <string.h>
#include "wstdio.h"
#include "tty.h"
//========================================================================\\
// Declarations
//========================================================================\\
#define COM1 "com1"
#define COM2 "com2"
#define CommSettings "com1:96,n,8,1"
#define BufMax 160 // Size of line buffer used for displaying text
#define cbInBuf 1024 // Size of receive buffer
#define cbOutBuf 128 // size of transmit buffer
DCB CommDCB; // DCB for comm port
int PortID; // The comm port id
COMSTAT CommStat; // COMSTAT info buffer for comm port
char MsgBuff[BufMax + 1]; // Buffer to hold incoming characters
BOOL bConnected; // Flag to indicate if connected
short nCommErr; // Storage for communications error data
WORD wCommEvt; // Storage for communications event data
HWND hTTYWnd; // Handle to application window
char sTemp[256];
static HANDLE hInst; // Global instance handle
FARPROC lpprocAbout; // Pointer to "About" dialog box procedure
FARPROC lpfnOldTTYProc; // Pointer to TTY proc prior to subclassing
long FAR PASCAL TTYWndProc(HWND, unsigned, WORD, LONG);
//========================================================================\\
// FUNCTION: About(HWND, unsigned, WORD, LONG)
// PURPOSE: Processes messages for About dialog box.
//========================================================================\\
BOOL FAR PASCAL About( hDlg, message, wParam, lParam )
HWND hDlg;
unsigned message;
WORD wParam;
LONG lParam;
{
if (message == WM_COMMAND
|| message == WM_LBUTTONDOWN) {
// if we click the mouse in the dialog, or press 'Enter', then go away
EndDialog( hDlg, TRUE );
return TRUE;
}
else if (message == WM_INITDIALOG)
return TRUE;
else return FALSE;
}
//========================================================================\\
// FUNCTION: AboutInit(HWND, HANDLE)
// PURPOSE: About box initialization.
//========================================================================\\
BOOL AboutInit(HWND hWnd, HANDLE hInstance)
{
HMENU hMenu;
/* Bind callback function with module instance */
lpprocAbout = MakeProcInstance( (FARPROC)About, hInstance );
return TRUE;
}
//========================================================================\\
// FUNCTION: SettingDlgProc(HWND, unsigned, WORD, LONG)
// PURPOSE: Processes messages for Communications Settings dialog.
//========================================================================\\
BOOL FAR PASCAL SettingDlgProc( hDlg, message, wParam, lParam )
HWND hDlg;
unsigned message;
WORD wParam;
LONG lParam;
{
int theButton;
static DCB dlgDCB;
switch(message) {
case WM_COMMAND:
// if the Ok button is pressed the new settings are saved
if(wParam == IDOK) {
// save the new settings
CommDCB = dlgDCB;
// close the dialog
EndDialog( hDlg, TRUE );
} else
// otherwise, the settings are not saved and changes are discarded
if(wParam == IDCANCEL)
EndDialog(hDlg,FALSE);
else
if(HIWORD(lParam) == BN_CLICKED) {
// if a button is clicked and it is a radiobutton,
// then we uncheck the current selection and check
// the one that was clicked.
HWND hStartWnd = GetDlgItem(hDlg,wParam);
if(LOWORD(GetWindowLong(hStartWnd,GWL_STYLE))
== BS_AUTORADIOBUTTON){
HWND hCurrWnd = hStartWnd;
do{
hCurrWnd = GetNextDlgGroupItem(hDlg,hCurrWnd,1);
SendMessage(hCurrWnd, BM_SETCHECK, hCurrWnd == hStart
} while(hCurrWnd != hStartWnd);
}
// now we set the appropriate value in the DCB for the
// button that was clicked
switch (wParam){
case RBBAUD_300: dlgDCB.BaudRate = 300; break;
case RBBAUD_1200: dlgDCB.BaudRate = 1200; break;
case RBBAUD_2400: dlgDCB.BaudRate = 2400; break;
case RBBAUD_9600: dlgDCB.BaudRate = 9600; break;
case RBDBITS_7: dlgDCB.ByteSize = 7; break;
case RBDBITS_8: dlgDCB.ByteSize = 8; break;
case RBPARITY_EVEN: dlgDCB.Parity = EVENPARITY; b
case RBPARITY_ODD: dlgDCB.Parity = ODDPARITY; bre
case RBPARITY_NONE: dlgDCB.Parity = NOPARITY; break;
case RBSBITS_2: dlgDCB.StopBits = TWOSTOPBITS; br
case RBSBITS_1: dlgDCB.StopBits = ONESTOPBIT; break;
case CBXONXOFF: dlgDCB.fInX = dlgDCB.fInX?0:1; break;
case RBPORT_COM1: dlgDCB.Id = 1; break;
case RBPORT_COM2: dlgDCB.Id = 2; break;
}
} else
return FALSE;
break;
case WM_INITDIALOG:
// make a copy of the current DCB
// we will change this copy, and copy back to the original
// if we click Ok
dlgDCB = CommDCB;
// set buttons as reflected by the current DCB
// if the current port isn't com2, set com1 button
theButton = (dlgDCB.Id == 2 ? RBPORT_COM2 : RBPORT_COM1);
SendDlgItemMessage(hDlg,theButton,BM_SETCHECK,1,0L);
// set baud button
switch(dlgDCB.BaudRate){
case 300: theButton = RBBAUD_300; break;
case 1200: theButton = RBBAUD_1200; break;
case 2400: theButton = RBBAUD_2400; break;
case 9600: theButton = RBBAUD_9600; break;
default: theButton = RBBAUD_300; break;
}
SendDlgItemMessage(hDlg,theButton,BM_SETCHECK,1,0L);
// set data bits button. if it's not 8, then it's 7
theButton = (dlgDCB.ByteSize == 8 ? RBDBITS_8 : RBDBITS_7);
SendDlgItemMessage(hDlg,theButton,BM_SETCHECK,1,0L);
// set parity button
switch(dlgDCB.Parity){
case EVENPARITY: theButton = RBPARITY_EVEN; break;
case ODDPARITY: theButton = RBPARITY_ODD; break;
case NOPARITY: theButton = RBPARITY_NONE; break;
default: theButton = RBPARITY_NONE; break;
}
SendDlgItemMessage(hDlg,theButton,BM_SETCHECK,1,0L);
// set stop bits button. if it's not 2, then it's 1
theButton = (dlgDCB.StopBits == TWOSTOPBITS ? RBSBITS_2 : RBS
SendDlgItemMessage(hDlg,theButton,BM_SETCHECK,1,0L);
// set Xon/Xoff check box to on or off
SendDlgItemMessage(hDlg,CBXONXOFF,BM_SETCHECK,dlgDCB.fInX,0L);
break;
default:
return FALSE;
}
return TRUE;
}
//========================================================================\\
// FUNCTION: WinMain(HANDLE, HANDLE, LPSTR, int)
// PURPOSE: Main procedure of the application.
//========================================================================\\
int PASCAL WinMain( hInstance, hPrevInstance, lpszCmdLine, cmdShow )
HANDLE hInstance, hPrevInstance;
LPSTR lpszCmdLine;
int cmdShow;
{
MSG msg;
BOOL bMsgAvail;
short iNumRead,iError;
hInst = hInstance;
// initialize the stdio window library
if(!hPrevInstance)
if(!stdioInit(hInstance)) return FALSE;
// create a stdio window
if(!(hTTYWnd = CreateStdioWindow(
"TTY",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
hInstance,
TRUE)))
return FALSE;
// subclass the stdio window
lpfnOldTTYProc = (FARPROC) SetWindowLong(hTTYWnd,GWL_WNDPROC,
(DWORD) TTYWndProc);
// add the about box to the system menu
AboutInit(hTTYWnd,hInstance);
// add the terminal menu
SetMenu(hTTYWnd,LoadMenu(hInstance, "TTYMENU"));
// set the application icon
SetClassWord(hTTYWnd, GCW_HICON,
LoadIcon( hInstance, MAKEINTRESOURCE(TTYICON) ));
bConnected = FALSE;
// initialize the DCB to default settings
if(BuildCommDCB(CommSettings,&CommDCB) != 0) {
MessageBox(GetFocus(),"Error Building DCB!","",MB_OK);
}
CommDCB.CtsTimeout = 100; // Set Cts Timeout value
CommDCB.DsrTimeout = 100; // Set Dsr Timeout value
CommDCB.fOutX = 1; // output Xon/Xoff flow control on
CommDCB.fInX = 1; // input Xon/Xoff flow control on
CommDCB.XonChar = 0x11; // specify the Xon character
CommDCB.XoffChar = 0x13; // specify the Xoff character
CommDCB.fNull = 1; // strip null characters
CommDCB.XonLim = 30; // distance from queue empty to Xon
CommDCB.XoffLim = (cbInBuf/2) + 1; // distance from queue full to Xoff
CommDCB.fBinary = 0;
// show the window
ShowWindow( hTTYWnd, cmdShow );
UpdateWindow( hTTYWnd );
// PeekMessage loop to poll the comm port and pull messages from the queu
// if there is a message available, process it.
// otherwise, check the port and handle any available characters.
while(TRUE){
bMsgAvail = PeekMessage(&msg,NULL,0,0,PM_REMOVE);
if(bMsgAvail){
if(msg.message == WM_QUIT) break;
TranslateMessage((LPMSG)&msg);
DispatchMessage((LPMSG)&msg);
} else {
// check the comm port and process any available
// characters. you could also use a timer instead, and have
// the timer case of the wndproc check the port.
if(bConnected){
// get the CommStat record and get the # of characters availa
GetCommError(CommDCB.Id,&CommStat);
// get the number of characters available
iNumRead = CommStat.cbInQue;
if(iNumRead > 0) {
// get the number of characters rounded to the buffer siz
if(iNumRead > BufMax) iNumRead = BufMax;
// read the characters
iNumRead = ReadComm(CommDCB.Id,MsgBuff,
iNumRead);
// check for errors
if(iNumRead < 0) {
iNumRead = -iNumRead;
nCommErr = GetCommError(CommDCB.Id,&CommStat);
// clear the event mask
wCommEvt = GetCommEventMask(CommDCB.Id,0xFFFF);
// display what the error was
LoadString(hInst, nCommErr, sTemp, 20);
MessageBox(GetFocus(), sTemp, "Comm Read Error!",MB_O
}
MsgBuff[iNumRead] = '\0';
// send the characters to the tty window for processing
SendMessage(hTTYWnd,COMM_CHARS,
iNumRead,(LONG)(LPSTR)MsgBuff);
//wputs((LPSTR) MsgBuff); // could just do this instead
}
}
}
}
}
//========================================================================\\
// FUNCTION: TTYWndProc(HWND, unsigned, WORD, LONG)
// PURPOSE: Processes messages for the terminal window.
//========================================================================\\
long FAR PASCAL TTYWndProc( hWnd, message, wParam, lParam )
HWND hWnd;
unsigned message;
WORD wParam;
LONG lParam;
{
FARPROC lpSettingDlgProc;
char szErr[22];
unsigned nErr;
switch (message)
{
case WM_DESTROY:
PostQuitMessage( 0 );
break;
case WM_ENDSESSION:
if (wParam && bConnected)
SendMessage(hWnd, WM_COMMAND, TTYCONNECT, 1L);
break;
case WM_CLOSE:
// disconnect if still connected
if(bConnected)SendMessage(hWnd,WM_COMMAND,TTYCONNECT,0L);
// go ahead and close down
return CallWindowProc(lpfnOldTTYProc,hWnd,
message,wParam,lParam);
break;
case WM_COMMAND:
switch(wParam){
case IDSABOUT:
DialogBox( hInst, MAKEINTRESOURCE(ABOUTBOX), hWnd, lpprocAbout );
break;
case TTYEXIT:
PostMessage(hWnd,WM_CLOSE,0,0L);
break;
case TTYCONNECT:
// connect to port if not already connected
if(!bConnected){
if((PortID = OpenComm((CommDCB.Id == 2?COM2:COM1),cbInBuf,cbOutBuf)) < 0)
MessageBox(hWnd,"Error Opening Comm Port!","",MB_OK);
break;
}
FlushComm(PortID,0);
FlushComm(PortID,1);
CommDCB.Id = PortID;
if(CommDCB.fInX) {
CommDCB.fOutX = 1; // enable output Xon/Xoff flow ctl
CommDCB.fInX = 1; // enable input Xon/Xoff flow ctl
CommDCB.fRtsflow = 0; // disable hardware flow ctl
CommDCB.fDtrflow = 0; // disable hardware flow ctl
} else {
CommDCB.fOutX = 0; // disable ouput Xon/Xoff flow ctl
CommDCB.fInX = 0; // disable input Xon/Xoff flow ctl
CommDCB.fRtsflow = 1; // enable hardware flow ctl
CommDCB.fDtrflow = 1; // enable hardware flow ctl
}
if(SetCommState(&CommDCB) !=0 ){
MessageBox(hWnd,"Error Setting CommState!","",MB_OK);
break;
}
bConnected = TRUE;
CheckMenuItem(GetMenu(hWnd),TTYCONNECT,MF_CHECKED);
EnableMenuItem(GetMenu(hWnd),TTYSETTINGS,MF_DISABLED | MF_GRA
MessageBox(hWnd,"Connection was successful.","",MB_OK);
}else{
// otherwise disconnect
FlushComm(CommDCB.Id,0);
FlushComm(CommDCB.Id,1);
CloseComm(CommDCB.Id);
if (!lParam)
MessageBox(hWnd,"Connection closed.","",MB_OK);
bConnected = FALSE;
CheckMenuItem(GetMenu(hWnd),TTYCONNECT,MF_UNCHECKED);
EnableMenuItem(GetMenu(hWnd),TTYSETTINGS,MF_ENABLED);
}
break;
case TTYSETTINGS:
// settings dialog
lpSettingDlgProc = MakeProcInstance(SettingDlgProc,hInst);
DialogBox(hInst,"SETTINGSDLG",hWnd,lpSettingDlgProc);
FreeProcInstance(lpSettingDlgProc);
break;
}
break;
case WM_CHAR:
if(!bConnected) break;
// if we're connected, send any keyboard characters to the port
nCommErr = WriteComm(CommDCB.Id,(LPSTR) &wParam,1);
if(nCommErr != 1) {
nCommErr = GetCommError(CommDCB.Id,&CommStat);
if(nCommErr != 0) {
sTemp[0] = 0;
for (nErr = 1; nErr != 0; nErr = nErr << 1) {
if (nErr & nCommErr) {
LoadString(hInst, nErr, szErr, 20);
strcat(sTemp, szErr);
strcat(sTemp, "\n");
}
}
MessageBox(hWnd, sTemp, "Comm Write Error!", MB_OK);
}
wCommEvt = GetCommEventMask(CommDCB.Id, 0xFFFF);
}
break;
case COMM_CHARS:
// display available characters
if(wParam > 0)
wputs((LPSTR) lParam);
break;
// Pass all other messages to class's window procedure, since window
// was subclassed
default:
return CallWindowProc(lpfnOldTTYProc,hWnd,
message,wParam,lParam);
break;
}
return(0L);
}
WSTDIO.C
CD-ROM Disc Path: \SAMPCODE\WIN_SDK\TTY\WSTDIO.C
//
// FILE: WSTDIO.c
// PURPOSE: Contains functions for managing a standard I/O window.
// Provides a means for easily sending text to a window
// for debugging, etc.
// FUNCTIONS:
// SetupStdioDC() - Initializes DC.
// ResetStdioDC() - Selects former font into DC.
// GetStdioLine() - Returns pointer to specified line in buffer.
// StdioUpdate() - Scroll and update displayed text.
// putStdio() - Process I/O window messages.
// StdioPaint() - Paint procedure for I/O window.
// InitStdio() - Initialize values used by I/O window.
// stdioInit() - Define/register I/O window class.
// wopen() - Create a default I/O window.
// CreateStdioWindow() - Create a customized I/O window.
// wputs() - Puts a string in the I/O window.
// StdioWndProc() - Processes messages for the I/O window.
//
#include <windows.h>
#include "wstdio.h"
//========================================================================\\
// Declarations
//========================================================================\\
#define MaxLines 25
#define MaxLine MaxLines - 1
char sScrBuff[MaxLines][81]; // Array of characters on TTY
// could make this heap object so can reallo
short nFirstLine; // Index of first line on TTY in the array
short nLastLine; // Index of last line on TTY in the array
short nCurrPos; // Current TTY line output position
short nStdioCharWidth,
nStdioCharHeight; // width and height of Stdio font chars
DWORD StdiobkRGB; // background color
DWORD StdiotextRGB; // text color
#define Stdio_FONT SYSTEM_FIXED_FONT // font used for display
HFONT hOldFont;
HWND hWndStdio = NULL; // Handle to standard I/O window
HANDLE hStdioInst;
BOOL bStdioQuit;
BOOL bInited = FALSE;
//========================================================================\\
// FUNCTION: SetupStdioDC(HWND, HDC)
// PURPOSE: Sets up the I/O window DC. Called at GetDC/BeginPaint time.
//========================================================================\\
void SetupStdioDC(HWND hWnd, HDC hDC)
{
RECT rClRect;
GetClientRect(hWnd,&rClRect);
// set origin to 25(+1 extra) lines from the bottom of the window
SetViewportOrg(hDC,0,rClRect.bottom - ((MaxLines+1) * nStdioCharHeight));
SetMapMode(hDC, MM_ANISOTROPIC);
// Set the extents such that one unit horizontally or
// vertically is one character width or height.
SetWindowExt(hDC,1,1);
// Set the viewport such that the last line in the buffer is
// displayed at the bottom of the window.
SetViewportExt(hDC,nStdioCharWidth,nStdioCharHeight);
// Set the background mode to opaque, and select the font.
SetBkMode(hDC,OPAQUE);
hOldFont = SelectObject(hDC,GetStockObject(Stdio_FONT));
}
//========================================================================\\
// FUNCTION: ResetStdioDC(HDC)
// PURPOSE: Prepare to release the DC by selecting the system font.
//========================================================================\\
void ResetStdioDC(HDC hDC)
{
SelectObject(hDC,hOldFont);
}
//========================================================================\\
// FUNCTION: GetStdioLine(short)
// PURPOSE: Return a pointer to the specified line of the display.
//========================================================================\\
char *GetStdioLine(short ndx)
{
short pos;
// find the first line (one past the last line since we have a
// circular buffer). index to the desired line from there.
pos = nLastLine + 1;
if(pos == MaxLines) pos = 0;
pos = pos + ndx;
if(pos > MaxLine) pos = pos - MaxLines;
return(sScrBuff[pos]);
}
//========================================================================\\
// FUNCTION: StdioUpdate(HWND, HDC, int)
// PURPOSE: Scroll the window by the number of lines we have received,
// and display the text in the invalidated areas.
//========================================================================\\
void StdioUpdate(HWND hWnd, HDC hDC, int iLinesOut)
{
RECT rcRect;
if(iLinesOut > 0){
// scroll screen by number of lines received
GetClientRect(hWnd,&rcRect);
rcRect.bottom -= nStdioCharHeight;
ScrollWindow(hWnd,0,-(nStdioCharHeight * iLinesOut),&rcRect,NULL);
}
UpdateWindow(hWnd);
}
//========================================================================\\
// FUNCTION: putStdio(HWND, HDC, WORD, LPSTR)
// PURPOSE: Process incoming text to Stdio window.
//========================================================================\\
void putStdio(HWND hWnd, HDC hDC, WORD wParam, LPSTR lParam)
{
short i, j;
char *sBuffer;
RECT rClRect, rcInvalid;
char *psLine;
short iLinesOut = 0; // # of lines to scroll
sBuffer = sScrBuff[nLastLine]; // pointer to current line
// scan the text, handle any special characters, and display the rest.
for(i=0; i<wParam; i++){
switch(lParam[i]) {
case '\r': // return
// move to the start of the line
nCurrPos = 0; // reset the current position in the line
break;
case '\n': // new line
// "scroll" the window
++iLinesOut; // increment lines to scroll
nCurrPos = 0; // reset the current position in the line
++nLastLine;
if(nLastLine > MaxLine) nLastLine = 0;
// clear the new line
sBuffer = sScrBuff[nLastLine];
for(j=0; j<80; j++) sBuffer[j] = '\0';
break;
case '\b': // backspace
// move back one space
if(nCurrPos > 0) {
--nCurrPos;
sBuffer[nCurrPos] = '\0';
rcInvalid.top = MaxLine; rcInvalid.bottom = MaxLine + 1;
rcInvalid.left = nCurrPos;
rcInvalid.right = nCurrPos + 1;
LPtoDP(hDC,(POINT *) &rcInvalid, 2);
// invalidate the area so that it gets redrawn
InvalidateRect(hWnd,&rcInvalid, TRUE);
}
break;
case '\t':
// ignore tabs for now
break;
default:
//add char to buffer
if(nCurrPos < 80){
// put the character in the screen buffer
sBuffer[nCurrPos] = lParam[i]; // add char to screen line
// calculate area to invalidate
rcInvalid.top = MaxLine; rcInvalid.bottom = MaxLine + 1;
rcInvalid.left = nCurrPos;
++nCurrPos;
rcInvalid.right = nCurrPos;
// only need to invalidate the area if it is on the last line
if(iLinesOut == 0) {
LPtoDP(hDC,(POINT *) &rcInvalid, 2);
// invalidate the area so that it gets redrawn
InvalidateRect(hWnd,&rcInvalid, FALSE);
}
}
break;
}
// force scroll after 2 lines. you will scroll faster if you increase
// this, but it may not look good.
if(iLinesOut > 2) {
StdioUpdate(hWnd, hDC, iLinesOut);
iLinesOut = 0;
}
}
// force scroll and update at the end of each bunch of characters.
StdioUpdate(hWnd, hDC, iLinesOut);
}
//========================================================================\\
// FUNCTION: StdioPaint(HWND)
// PURPOSE: The I/O window paint procedure. Draws necessary text in
// the window.
//========================================================================\\
void StdioPaint(HWND hWnd )
{
char *psLine;
register int i;
PAINTSTRUCT ps;
HDC hDC;
RECT rcUpdate, rcClient;
int nVPaintBeg, nVPaintEnd, nHPaintBeg, nHPaintEnd;
hDC = BeginPaint( hWnd, (LPPAINTSTRUCT)&ps );
SetupStdioDC(hWnd,hDC);
rcUpdate = ps.rcPaint;
DPtoLP(hDC,(POINT *) &rcUpdate, 2);
// calculate first and last lines to update
nVPaintBeg = max (0, rcUpdate.top);
nVPaintEnd = min (MaxLines, rcUpdate.bottom);
// calculate the first and last columns to update
nHPaintBeg = max (0, rcUpdate.left);
nHPaintEnd = min (80, rcUpdate.right);
// display the lines that need to be drawn
for(i=nVPaintBeg; i<nVPaintEnd; i++){
psLine = GetStdioLine(i) + nHPaintBeg;
TextOut(hDC,
nHPaintBeg,
i,
psLine,
strlen(psLine));
}
ResetStdioDC(hDC);
EndPaint( hWnd, (LPPAINTSTRUCT)&ps );
}
//========================================================================\\
// FUNCTION: InitStdio(HWND)
// PURPOSE: Initialize variables used by I/O window.
//========================================================================\\
void InitStdio(HWND hWnd)
{
int i,j;
HDC hDC;
TEXTMETRIC Metrics;
// initialize screen buffer to nulls
for(i=0; i<MaxLines; i++)
for(j=0; j<81; j++)
sScrBuff[i][j] = '\0';
nFirstLine = 0;
nLastLine = MaxLine;
nCurrPos = 0;
// get the text metrics for the font we are using
hDC = GetDC(hWnd);
hOldFont = SelectObject(hDC,GetStockObject(Stdio_FONT));
GetTextMetrics(hDC,&Metrics);
SelectObject(hDC,hOldFont);
ReleaseDC(hWnd,hDC);
// calculate the height and width of the font
nStdioCharWidth = Metrics.tmMaxCharWidth;
nStdioCharHeight = Metrics.tmHeight + Metrics.tmExternalLeading;
// get the background and forground colors we are going to use
StdiobkRGB = GetSysColor(COLOR_WINDOW); // background color
StdiotextRGB = GetSysColor(COLOR_WINDOWTEXT); // text color
bInited = TRUE;
}
//========================================================================\\
// FUNCTION: stdioInit(HANDLE)
// PURPOSE: Initialize the stdio module. Registers the window class.
// RETURNS: Status of RegisterClass().
//========================================================================\\
BOOL stdioInit(HANDLE hInstance)
{
PWNDCLASS pStdioClass;
HWND hDummyWnd;
if(hInstance == NULL) return FALSE;
// create the stdio window
pStdioClass = (PWNDCLASS)LocalAlloc( LPTR, sizeof(WNDCLASS) );
pStdioClass->hCursor = LoadCursor( NULL, IDC_ARROW );
pStdioClass->lpszClassName = (LPSTR)"Stdio";
pStdioClass->hbrBackground = COLOR_WINDOW + 1;
pStdioClass->hInstance = hInstance;
pStdioClass->style = CS_HREDRAW | CS_VREDRAW;
pStdioClass->lpfnWndProc = StdioWndProc;
if (!RegisterClass( (LPWNDCLASS)pStdioClass ) )
// Initialization failed.
// Windows will automatically deallocate all allocated memory.
return FALSE;
LocalFree( (HANDLE)pStdioClass );
hStdioInst = hInstance;
return TRUE;
}
//========================================================================\\
// FUNCTION: wopen(HWND, BOOL)
// PURPOSE: Create a default style stdio window. If bQuit is TRUE,
// PostQuitMessage will be called when the window is closed.
// Therefore, the stdio window can be used for the main
// application window.
// RETURNS: Handle to window created.
//========================================================================\\
HWND wopen(HWND hWndParent, BOOL bQuit)
{
// if window already created, return handle
if(hWndStdio != NULL) return hWndStdio;
hWndStdio = CreateWindow((LPSTR)"Stdio",
(LPSTR)"STDIO",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
(HWND)hWndParent,
(HMENU)NULL,
(HANDLE)hStdioInst,
(LPSTR)NULL
);
if(hWndStdio == NULL) return FALSE;
ShowWindow(hWndStdio, SW_SHOW);
UpdateWindow(hWndStdio);
bStdioQuit = bQuit;
return hWndStdio;
}
//========================================================================\\
// FUNCTION: CreateStdioWindow(LPSTR, DWORD, int, int, int, int, HWND,
// HANDLE, BOOL)
// PURPOSE: Create an I/O window with definable name, style, size, etc.
// RETURNS: Handle to window created.
//========================================================================\\
HWND CreateStdioWindow(LPSTR lpWindowName, DWORD dwStyle,
int X, int Y, int nWidth, int nHeight,
HWND hWndParent, HANDLE hInstance, BOOL bQuit)
{
// if window already created, return handle
if(hWndStdio != NULL) return hWndStdio;
hWndStdio = CreateWindow((LPSTR)"Stdio",
(LPSTR)lpWindowName,
dwStyle,
X,
Y,
nWidth,
nHeight,
(HWND)hWndParent,
(HMENU)NULL,
(HANDLE)hInstance,
(LPSTR)NULL);
if(hWndStdio == NULL) return FALSE;
bStdioQuit = bQuit;
return hWndStdio;
}
//========================================================================\\
// FUNCTION: wputs(LPSTR)
// PURPOSE: Equivalent to puts() stdio function. Currently, '\n' is
// not recognized as in '\r\n', as with normal puts(). Must
// send '\r\n' explicitly.
// RETURNS: Status of wopen(), if called, otherwise TRUE.
//========================================================================\\
BOOL wputs(LPSTR lpStr)
{
HDC hDC;
int nStrLen;
// if being used for quick and dirty text output, a stdio window
// will be opened if it hasn't been already.
if(hWndStdio == NULL) if(wopen(NULL, FALSE) == NULL) return FALSE;
hDC = GetDC(hWndStdio);
SetupStdioDC(hWndStdio,hDC);
nStrLen = lstrlen(lpStr);
putStdio(hWndStdio,hDC,nStrLen,(LPSTR)lpStr);
ResetStdioDC(hDC);
ReleaseDC(hWndStdio,hDC);
return TRUE;
}
//========================================================================\\
// FUNCTION: StdioWndProc(HWND, unsigned, WORD, LONG)
// PURPOSE: Process messages for the I/O window. This function should
// be exported in the application's .DEF file.
//========================================================================\\
long FAR PASCAL StdioWndProc( hWnd, message, wParam, lParam )
HWND hWnd;
unsigned message;
WORD wParam;
LONG lParam;
{
PAINTSTRUCT ps;
HDC hDC;
LPPOINT ptMinMaxInfo;
switch (message)
{
case WM_CREATE:
// initialize stdio variables
InitStdio(hWnd);
break;
case WM_SYSCOLORCHANGE:
// if the colors have been changed in the control panel,
// we need to change also.
StdiobkRGB = GetSysColor(COLOR_WINDOW); // background color
StdiotextRGB = GetSysColor(COLOR_WINDOWTEXT); // text color
return DefWindowProc( hWnd, message, wParam, lParam );
break;
case WM_GETMINMAXINFO:
if(!bInited) InitStdio(hWnd);
// constrain the sizing of the window to 80 by 25 characters.
ptMinMaxInfo = (LPPOINT) lParam;
ptMinMaxInfo[1].x = nStdioCharWidth * 80
+ 2 * GetSystemMetrics(SM_CXFRAME);
ptMinMaxInfo[1].y = nStdioCharHeight * 26
+ 2 * GetSystemMetrics(SM_CYFRAME);
ptMinMaxInfo[4].x = nStdioCharWidth * 80
+ 2 * GetSystemMetrics(SM_CXFRAME);
ptMinMaxInfo[4].y = nStdioCharHeight * 26
+ 2 * GetSystemMetrics(SM_CYFRAME);
break;
case WM_PAINT:
// repaint the Stdio window
StdioPaint(hWnd);
break;
case WM_DESTROY:
// if specified when created, PostQuitMessage should be called
// when the window is destroyed.
if(bStdioQuit)
PostQuitMessage(0);
break;
case WM_CLOSE:
// destroy stdio data
hWndStdio = NULL;
// go ahead and close down
// -- fall through to default --
default:
return DefWindowProc( hWnd, message, wParam, lParam );
break;
}
return(0L);
}
Microsoft Windows S.D.K. v3.0 Sample MASM Source Code
CLOCKDAT.ASM
CD-ROM Disc Path: \SAMPCODE\WIN_SDK\CLOCK\CLOCKDAT.ASM
title Hardware Dependent Parameters
%out config
page ,132
OEM segment public
dw 0, -7999
dw 836, -7956
dw 1663, -7825
dw 2472, -7608
dw 3253, -7308
dw 3999, -6928
dw 4702, -6472
dw 5353, -5945
dw 5945, -5353
dw 6472, -4702
dw 6928, -4000
dw 7308, -3253
dw 7608, -2472
dw 7825, -1663
dw 7956, -836
dw 8000, 0
dw 7956, 836
dw 7825, 1663
dw 7608, 2472
dw 7308, 3253
dw 6928, 4000
dw 6472, 4702
dw 5945, 5353
dw 5353, 5945
dw 4702, 6472
dw 3999, 6928
dw 3253, 7308
dw 2472, 7608
dw 1663, 7825
dw 836, 7956
dw 0, 7999
dw -836, 7956
dw -1663, 7825
dw -2472, 7608
dw -3253, 7308
dw -4000, 6928
dw -4702, 6472
dw -5353, 5945
dw -5945, 5353
dw -6472, 4702
dw -6928, 3999
dw -7308, 3253
dw -7608, 2472
dw -7825, 1663
dw -7956, 836
dw -7999, -0
dw -7956, -836
dw -7825, -1663
dw -7608, -2472
dw -7308, -3253
dw -6928, -4000
dw -6472, -4702
dw -5945, -5353
dw -5353, -5945
dw -4702, -6472
dw -3999, -6928
dw -3253, -7308
dw -2472, -7608
dw -1663, -7825
dw -836 , -7956
OEM ends
end
DLGOPENA.ASM
CD-ROM Disc Path: \SAMPCODE\WIN_SDK\SHOWDIB\DLGOPENA.ASM
title dlgopena.asm
;****************************************************************************
;* *
;* MODULE : DLGOPENA.ASM *
;* *
;* DESCRIPTION : Assembly language helper routines for DLGOPEN.C *
;* *
;* FUNCTIONS : chdir () - change to specified asciiz directory. *
;* *
;****************************************************************************
?WIN = 1
?PLM=1 ; PASCAL Calling convention is DEFAULT
?WIN=1 ; Windows calling convention
?386=0 ; Use 386 code?
include cmacros.inc
;*********************************************************************
;* The following structure should be used to access high and low
;* words of a DWORD. This means that "word ptr foo[2]" -> "foo.hi".
;*********************************************************************
LONG struc
lo dw ?
hi dw ?
LONG ends
FARPOINTER struc
off dw ?
sel dw ?
FARPOINTER ends
;*********************************************************************
; DATA SEGMENT DECLARATIONS
;*********************************************************************
ifndef SEGNAME
SEGNAME equ <TEXT>
endif
if ?386
.386p
createSeg _%SEGNAME, CodeSeg, word, use16, CODE
else
.286p
createSeg _%SEGNAME, CodeSeg, word, public, CODE
endif
sBegin DATA
sEnd DATA
sBegin CodeSeg
assumes CS,CodeSeg
assumes DS,DATA
;****************************************************************************
;* *
;* FUNCTION : chdir (p) *
;* *
;* PURPOSE : Change to asciiz directory specified in p *
;* *
;* RETURNS : 1 - Success *
;* 0 - Error *
;* *
;****************************************************************************
cProc chdir,<PUBLIC,FAR,PASCAL>,<ds>
parmD p
cBegin
lds dx,p
mov bx,dx
cmp BYTE PTR ds:[bx+1],':'
jnz chdnod ; No drive
mov dl,ds:[bx]
or dl,20h
sub dl,'a'
mov ah,0eh ; Set current drive
int 21h
mov ah,19h ; Get current drive
int 21h
cmp al,dl
jne chderror
lds dx,p
add dx,2
mov bx,dx
cmp BYTE PTR ds:[bx],0 ; If path name is "" we are there
jz chdok
chdnod:
mov ah,3bh
int 21h
jc chderror
chdok:
mov ax,1
chdexit:
cEnd
chderror:
xor ax,ax
jmp short chdexit
sEnd CodeSeg
end
GETTIME.ASM
CD-ROM Disc Path: \SAMPCODE\WIN_SDK\CLOCK\GETTIME.ASM
; get the time more efficiently than cmerge and DOSCALL() do
?PLM=0
include cmacros.inc
time struc
hour dw ?
minute dw ?
second dw ?
time ends
assumes CS,CODE
assumes DS,DATA
sBegin CODE
cProc GetTime, <PUBLIC, NEAR>
parmW pTime ; pointer to the structure to fill
cBegin
mov ax, 2c00h ; get time
int 21h
mov bx, pTime
cmp ch, 12 ; if hour <12
jl lt12 ; we're ok
sub ch,12 ; else adjust it
lt12:
xor ax,ax
mov al,ch
mov [bx].hour, ax
mov al,cl
mov [bx].minute, ax
mov al,dh
mov [bx].second, ax
cEnd
sEnd CODE
END
LIBENTRY.ASM
CD-ROM Disc Path: \SAMPCODE\WIN_SDK\SELECT\LIBENTRY.ASM
PAGE,132
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; LIBENTRY.ASM
;
; Windows dynamic link library entry routine
;
; This module generates a code segment called INIT_TEXT.
; It initializes the local heap if one exists and then calls
; the C routine LibMain() which should have the form:
; BOOL FAR PASCAL LibMain(HANDLE hInstance,
; WORD wDataSeg,
; WORD cbHeap,
; LPSTR lpszCmdLine);
;
; The result of the call to LibMain is returned to Windows.
; The C routine should return TRUE if it completes initialization
; successfully, FALSE if some error occurs.
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
include cmacros.inc
externFP <LibMain> ; the C routine to be called
createSeg INIT_TEXT, INIT_TEXT, BYTE, PUBLIC, CODE
sBegin INIT_TEXT
assumes CS,INIT_TEXT
?PLM=0 ; 'C'naming
externA <_acrtused> ; ensures that Win DLL startup code is linke
?PLM=1 ; 'PASCAL' naming
externFP <LocalInit> ; Windows heap init routine
cProc LibEntry, <PUBLIC,FAR> ; entry point into DLL
cBegin
push di ; handle of the module instance
push ds ; library data segment
push cx ; heap size
push es ; command line segment
push si ; command line offset
; if we have some heap then initialize it
jcxz callc ; jump if no heap specified
; call the Windows function LocalInit() to set up the heap
; LocalInit((LPSTR)start, WORD cbHeap);
xor ax,ax
cCall LocalInit <ds, ax, cx>
or ax,ax ; did it do it ok ?
jz error ; quit if it failed
; invoke the C routine to do any special initialization
callc:
call LibMain ; invoke the 'C' routine (result in AX)
jmp short exit ; LibMain is responsible for stack clean up
error:
pop si ; clean up stack on a LocalInit error
pop es
pop cx
pop ds
pop di
exit:
cEnd
sEnd INIT_TEXT
end LibEntry
LIBENTRY.ASM
CD-ROM Disc Path: \SAMPCODE\WIN_SDK\RAINBOW\LIBENTRY.ASM
PAGE,132
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; LIBENTRY.ASM
;
; Windows dynamic link library entry routine
;
; This module generates a code segment called INIT_TEXT.
; It initializes the local heap if one exists and then calls
; the C routine LibMain() which should have the form:
; BOOL FAR PASCAL LibMain(HANDLE hInstance,
; WORD wDataSeg,
; WORD cbHeap,
; LPSTR lpszCmdLine);
;
; The result of the call to LibMain is returned to Windows.
; The C routine should return TRUE if it completes initialization
; successfully, FALSE if some error occurs.
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
include cmacros.inc
externFP <LibMain> ; the C routine to be called
createSeg INIT_TEXT, INIT_TEXT, BYTE, PUBLIC, CODE
sBegin INIT_TEXT
assumes CS,INIT_TEXT
?PLM=0 ; 'C'naming
externA <_acrtused> ; ensures that Win DLL startup code is linke
?PLM=1 ; 'PASCAL' naming
externFP <LocalInit> ; Windows heap init routine
cProc LibEntry, <PUBLIC,FAR> ; entry point into DLL
cBegin
push di ; handle of the module instance
push ds ; library data segment
push cx ; heap size
push es ; command line segment
push si ; command line offset
; if we have some heap then initialize it
jcxz callc ; jump if no heap specified
; call the Windows function LocalInit() to set up the heap
; LocalInit((LPSTR)start, WORD cbHeap);
xor ax,ax
cCall LocalInit <ds, ax, cx>
or ax,ax ; did it do it ok ?
jz error ; quit if it failed
; invoke the C routine to do any special initialization
callc:
call LibMain ; invoke the 'C' routine (result in AX)
jmp short exit ; LibMain is responsible for stack clean up
error:
pop si ; clean up stack on a LocalInit error
pop es
pop cx
pop ds
pop di
exit:
cEnd
sEnd INIT_TEXT
end LibEntry
Programming Windows (C. Petzold) Sample `C' Source Code
ABOUT1.C
CD-ROM Disc Path: \SAMPCODE\PROGWIN\CHAP10\ABOUT1.C
/*------------------------------------------
ABOUT1.C -- About Box Demo Program No. 1
(c) Charles Petzold, 1990
------------------------------------------*/
#include <windows.h>
#include "about1.h"
long FAR PASCAL WndProc (HWND, WORD, WORD, LONG);
int PASCAL WinMain (HANDLE hInstance, HANDLE hPrevInstance,
LPSTR lpszCmdLine, int nCmdShow)
{
static char szAppName [] = "About1" ;
MSG msg;
HWND hwnd ;
WNDCLASS wndclass ;
if (!hPrevInstance)
{
wndclass.style = CS_HREDRAW | CS_VREDRAW ;
wndclass.lpfnWndProc = WndProc ;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hInstance = hInstance ;
wndclass.hIcon = LoadIcon (hInstance, szAppName) ;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = GetStockObject (WHITE_BRUSH) ;
wndclass.lpszMenuName = szAppName ;
wndclass.lpszClassName = szAppName ;
RegisterClass (&wndclass) ;
}
hwnd = CreateWindow (szAppName, "About Box Demo Program",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL) ;
ShowWindow (hwnd, nCmdShow) ;
UpdateWindow (hwnd);
while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
return msg.wParam ;
}
BOOL FAR PASCAL AboutDlgProc (HWND hDlg, WORD message, WORD wParam, LONG lPar
{
switch (message)
{
case WM_INITDIALOG:
return TRUE ;
case WM_COMMAND:
switch (wParam)
{
case IDOK:
case IDCANCEL:
EndDialog (hDlg, 0) ;
return TRUE ;
}
break ;
}
return FALSE ;
}
long FAR PASCAL WndProc (HWND hwnd, WORD message, WORD wParam, LONG lParam)
{
static FARPROC lpfnAboutDlgProc ;
static HANDLE hInstance ;
switch (message)
{
case WM_CREATE:
hInstance = ((LPCREATESTRUCT) lParam)->hInstance ;
lpfnAboutDlgProc = MakeProcInstance (AboutDlgProc, hInstance)
return 0 ;
case WM_COMMAND:
switch (wParam)
{
case IDM_ABOUT:
DialogBox (hInstance, "AboutBox", hwnd,
lpfnAboutDlgProc) ;
return 0 ;
}
break ;
case WM_DESTROY :
PostQuitMessage (0) ;
return 0 ;
}
return DefWindowProc (hwnd, message, wParam, lParam) ;
}
ABOUT2.C
CD-ROM Disc Path: \SAMPCODE\PROGWIN\CHAP10\ABOUT2.C
/*------------------------------------------
ABOUT2.C -- About Box Demo Program No. 2
(c) Charles Petzold, 1990
------------------------------------------*/
#include <windows.h>
#include "about2.h"
long FAR PASCAL WndProc (HWND, WORD, WORD, LONG);
short nCurrentColor = IDD_BLACK,
nCurrentFigure = IDD_RECT ;
int PASCAL WinMain (HANDLE hInstance, HANDLE hPrevInstance,
LPSTR lpszCmdLine, int nCmdShow)
{
static char szAppName [] = "About2" ;
MSG msg;
HWND hwnd ;
WNDCLASS wndclass ;
if (!hPrevInstance)
{
wndclass.style = CS_HREDRAW | CS_VREDRAW ;
wndclass.lpfnWndProc = WndProc ;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hInstance = hInstance ;
wndclass.hIcon = LoadIcon (hInstance, szAppName) ;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = GetStockObject (WHITE_BRUSH) ;
wndclass.lpszMenuName = szAppName ;
wndclass.lpszClassName = szAppName ;
RegisterClass (&wndclass) ;
}
hwnd = CreateWindow (szAppName, "About Box Demo Program",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL) ;
ShowWindow (hwnd, nCmdShow) ;
UpdateWindow (hwnd);
while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
return msg.wParam ;
}
void PaintWindow (HWND hwnd, short nColor, short nFigure)
{
static DWORD dwColor [8] = { RGB (0, 0, 0), RGB ( 0, 0, 255),
RGB (0, 255, 0), RGB ( 0, 255, 255),
RGB (255, 0, 0), RGB (255, 0, 255),
RGB (255, 255, 0), RGB (255, 255, 255) } ;
HBRUSH hBrush ;
HDC hdc ;
RECT rect ;
hdc = GetDC (hwnd) ;
GetClientRect (hwnd, &rect) ;
hBrush = CreateSolidBrush (dwColor [nColor - IDD_BLACK]) ;
hBrush = SelectObject (hdc, hBrush) ;
if (nFigure == IDD_RECT)
Rectangle (hdc, rect.left, rect.top, rect.right, rect.bottom) ;
else
Ellipse (hdc, rect.left, rect.top, rect.right, rect.bottom) ;
DeleteObject (SelectObject (hdc, hBrush)) ;
ReleaseDC (hwnd, hdc) ;
}
void PaintTheBlock (HWND hCtrl, short nColor, short nFigure)
{
InvalidateRect (hCtrl, NULL, TRUE) ;
UpdateWindow (hCtrl) ;
PaintWindow (hCtrl, nColor, nFigure) ;
}
BOOL FAR PASCAL AboutDlgProc (HWND hDlg, WORD message, WORD wParam, LONG lPar
{
static HWND hCtrlBlock ;
static short nColor, nFigure ;
switch (message)
{
case WM_INITDIALOG:
nColor = nCurrentColor ;
nFigure = nCurrentFigure ;
CheckRadioButton (hDlg, IDD_BLACK, IDD_WHITE, nColor) ;
CheckRadioButton (hDlg, IDD_RECT, IDD_ELL, nFigure) ;
hCtrlBlock = GetDlgItem (hDlg, IDD_PAINT) ;
SetFocus (GetDlgItem (hDlg, nColor)) ;
return FALSE ;
case WM_COMMAND:
switch (wParam)
{
case IDOK:
nCurrentColor = nColor ;
nCurrentFigure = nFigure ;
EndDialog (hDlg, TRUE) ;
return TRUE ;
case IDCANCEL:
EndDialog (hDlg, FALSE) ;
return TRUE ;
case IDD_BLACK:
case IDD_RED:
case IDD_GREEN:
case IDD_YELLOW:
case IDD_BLUE:
case IDD_MAGENTA:
case IDD_CYAN:
case IDD_WHITE:
nColor = wParam ;
CheckRadioButton (hDlg, IDD_BLACK, IDD_WHITE, wParam
PaintTheBlock (hCtrlBlock, nColor, nFigure) ;
return TRUE ;
case IDD_RECT:
case IDD_ELL:
nFigure = wParam ;
CheckRadioButton (hDlg, IDD_RECT, IDD_ELL, wParam) ;
PaintTheBlock (hCtrlBlock, nColor, nFigure) ;
return TRUE ;
}
break ;
case WM_PAINT:
PaintTheBlock (hCtrlBlock, nColor, nFigure) ;
break ;
}
return FALSE ;
}
long FAR PASCAL WndProc (HWND hwnd, WORD message, WORD wParam, LONG lParam)
{
static FARPROC lpfnAboutDlgProc ;
static HANDLE hInstance ;
PAINTSTRUCT ps ;
switch (message)
{
case WM_CREATE:
hInstance = ((LPCREATESTRUCT) lParam)->hInstance ;
lpfnAboutDlgProc = MakeProcInstance (AboutDlgProc, hInstance)
return 0 ;
case WM_COMMAND:
switch (wParam)
{
case IDM_ABOUT:
if (DialogBox (hInstance, "AboutBox", hwnd,
lpfnAboutDlgProc))
InvalidateRect (hwnd, NULL, TRUE) ;
return 0 ;
}
break ;
case WM_PAINT:
BeginPaint (hwnd, &ps) ;
EndPaint (hwnd, &ps) ;
PaintWindow (hwnd, nCurrentColor, nCurrentFigure) ;
return 0 ;
case WM_DESTROY :
PostQuitMessage (0) ;
return 0 ;
}
return DefWindowProc (hwnd, message, wParam, lParam) ;
}
ABOUT3.C
CD-ROM Disc Path: \SAMPCODE\PROGWIN\CHAP10\ABOUT3.C
/*------------------------------------------
ABOUT3.C -- About Box Demo Program No. 3
(c) Charles Petzold, 1990
------------------------------------------*/
#include <windows.h>
#include "about3.h"
long FAR PASCAL WndProc (HWND, WORD, WORD, LONG) ;
long FAR PASCAL EllipPushWndProc (HWND, WORD, WORD, LONG) ;
int PASCAL WinMain (HANDLE hInstance, HANDLE hPrevInstance,
LPSTR lpszCmdLine, int nCmdShow)
{
static char szAppName [] = "About3" ;
MSG msg;
HWND hwnd ;
WNDCLASS wndclass ;
if (!hPrevInstance)
{
wndclass.style = CS_HREDRAW | CS_VREDRAW ;
wndclass.lpfnWndProc = WndProc ;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hInstance = hInstance ;
wndclass.hIcon = LoadIcon (hInstance, szAppName) ;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = GetStockObject (WHITE_BRUSH) ;
wndclass.lpszMenuName = szAppName ;
wndclass.lpszClassName = szAppName ;
RegisterClass (&wndclass) ;
wndclass.style = CS_HREDRAW | CS_VREDRAW ;
wndclass.lpfnWndProc = EllipPushWndProc ;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hInstance = hInstance ;
wndclass.hIcon = NULL ;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = COLOR_WINDOW + 1 ;
wndclass.lpszMenuName = NULL ;
wndclass.lpszClassName = "EllipPush" ;
RegisterClass (&wndclass) ;
}
hwnd = CreateWindow (szAppName, "About Box Demo Program",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL) ;
ShowWindow (hwnd, nCmdShow) ;
UpdateWindow (hwnd);
while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
return msg.wParam ;
}
BOOL FAR PASCAL AboutDlgProc (HWND hDlg, WORD message, WORD wParam, LONG lPar
{
switch (message)
{
case WM_INITDIALOG:
return TRUE ;
case WM_COMMAND:
switch (wParam)
{
case IDOK:
EndDialog (hDlg, 0) ;
return TRUE ;
}
break ;
}
return FALSE ;
}
long FAR PASCAL WndProc (HWND hwnd, WORD message, WORD wParam, LONG lParam)
{
static FARPROC lpfnAboutDlgProc ;
static HANDLE hInstance ;
switch (message)
{
case WM_CREATE:
hInstance = ((LPCREATESTRUCT) lParam)->hInstance ;
lpfnAboutDlgProc = MakeProcInstance (AboutDlgProc, hInstance)
return 0 ;
case WM_COMMAND:
switch (wParam)
{
case IDM_ABOUT:
DialogBox (hInstance, "AboutBox", hwnd,
lpfnAboutDlgProc) ;
return 0 ;
}
break ;
case WM_DESTROY :
PostQuitMessage (0) ;
return 0 ;
}
return DefWindowProc (hwnd, message, wParam, lParam) ;
}
long FAR PASCAL EllipPushWndProc (HWND hwnd, WORD message,
WORD wParam, LONG lParam)
{
char szText [40] ;
HBRUSH hBrush ;
HDC hdc ;
PAINTSTRUCT ps ;
RECT rect ;
switch (message)
{
case WM_PAINT:
GetClientRect (hwnd, &rect) ;
GetWindowText (hwnd, szText, sizeof szText) ;
hdc = BeginPaint (hwnd, &ps) ;
hBrush = CreateSolidBrush (GetSysColor (COLOR_WINDOW)) ;
hBrush = SelectObject (hdc, hBrush) ;
SetBkColor (hdc, GetSysColor (COLOR_WINDOW)) ;
SetTextColor (hdc, GetSysColor (COLOR_WINDOWTEXT)) ;
Ellipse (hdc, rect.left, rect.top, rect.right, rect.bottom) ;
DrawText (hdc, szText, -1, &rect,
DT_SINGLELINE | DT_CENTER | DT_VCENTER) ;
DeleteObject (SelectObject (hdc, hBrush)) ;
EndPaint (hwnd, &ps) ;
return 0 ;
case WM_KEYUP:
if (wParam != VK_SPACE)
break ;
// fall through
case WM_LBUTTONUP:
SendMessage (GetParent (hwnd), WM_COMMAND,
GetWindowWord (hwnd, GWW_ID), (LONG) hwnd) ;
return 0 ;
}
return DefWindowProc (hwnd, message, wParam, lParam) ;
}
ARCS.C
CD-ROM Disc Path: \SAMPCODE\PROGWIN\CHAP12\ARCS.C
/*-------------------------------------------------------
ARCS.C -- Demonstrates Drawing Arcs, Chords, and Pies
(c) Charles Petzold, 1990
-------------------------------------------------------*/
#include <windows.h>
#include "arcs.h"
long FAR PASCAL WndProc (HWND, WORD, WORD, LONG) ;
int PASCAL WinMain (HANDLE hInstance, HANDLE hPrevInstance,
LPSTR lpszCmdLine, int nCmdShow)
{
static char szAppName[] = "Arcs" ;
HWND hwnd ;
MSG msg ;
WNDCLASS wndclass ;
if (!hPrevInstance)
{
wndclass.style = CS_HREDRAW | CS_VREDRAW ;
wndclass.lpfnWndProc = WndProc ;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hInstance = hInstance ;
wndclass.hIcon = NULL ;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = GetStockObject (WHITE_BRUSH) ;
wndclass.lpszMenuName = szAppName ;
wndclass.lpszClassName = szAppName ;
RegisterClass (&wndclass) ;
}
hwnd = CreateWindow (szAppName, "Arcs, Chords, and Pies",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL) ;
ShowWindow (hwnd, nCmdShow) ;
UpdateWindow (hwnd) ;
while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
return msg.wParam ;
}
long FAR PASCAL WndProc (HWND hwnd, WORD message, WORD wParam, LONG lParam)
{
static short cxClient, cyClient, x1, x2, x3, x4, y1, y2, y3, y4,
nFigure = IDM_ARC ;
HDC hdc ;
HMENU hMenu ;
HPEN hPen ;
PAINTSTRUCT ps ;
short x, y ;
switch (message)
{
case WM_SIZE:
x3 = y3 = 0 ;
x4 = cxClient = LOWORD (lParam) ;
y4 = cyClient = HIWORD (lParam) ;
x2 = 3 * (x1 = cxClient / 4) ;
y2 = 3 * (y1 = cyClient / 4) ;
return 0 ;
case WM_COMMAND:
switch (wParam)
{
case IDM_ARC:
case IDM_CHORD:
case IDM_PIE:
hMenu = GetMenu (hwnd) ;
CheckMenuItem (hMenu, nFigure, MF_UNCHECKED) ;
CheckMenuItem (hMenu, nFigure = wParam, MF_CHECKED)
InvalidateRect (hwnd, NULL, FALSE) ;
return 0 ;
}
break ;
case WM_LBUTTONDOWN:
if (!(wParam & MK_SHIFT))
{
x3 = LOWORD (lParam) ;
y3 = HIWORD (lParam) ;
InvalidateRect (hwnd, NULL, TRUE) ;
return 0 ;
}
// fall through for MK_SHIFT
case WM_RBUTTONDOWN:
x4 = LOWORD (lParam) ;
y4 = HIWORD (lParam) ;
InvalidateRect (hwnd, NULL, TRUE) ;
return 0 ;
case WM_PAINT:
hdc = BeginPaint (hwnd, &ps) ;
hPen = SelectObject (hdc, CreatePen (PS_DOT, 1, 0L)) ;
Rectangle (hdc, x1, y1, x2, y2) ;
Ellipse (hdc, x1, y1, x2, y2) ;
DeleteObject (SelectObject (hdc, CreatePen (PS_SOLID, 3, 0L)))
switch (nFigure)
{
case IDM_ARC:
Arc (hdc, x1, y1, x2, y2, x3, y3, x4, y4) ;
break ;
case IDM_CHORD:
Chord (hdc, x1, y1, x2, y2, x3, y3, x4, y4) ;
break ;
case IDM_PIE:
Pie (hdc, x1, y1, x2, y2, x3, y3, x4, y4) ;
break ;
}
DeleteObject (SelectObject (hdc, hPen)) ;
MoveTo (hdc, x3, y3) ;
LineTo (hdc, cxClient / 2, cyClient / 2) ;
LineTo (hdc, x4, y4) ;
EndPaint (hwnd, &ps) ;
return 0 ;
case WM_DESTROY:
PostQuitMessage (0) ;
return 0 ;
}
return DefWindowProc (hwnd, message, wParam, lParam) ;
}
BEEPER1.C
CD-ROM Disc Path: \SAMPCODE\PROGWIN\CHAP05\BEEPER1.C
/*-----------------------------------------
BEEPER1.C -- Timer Demo Program No. 1
(c) Charles Petzold, 1990
-----------------------------------------*/
#include <windows.h>
#define ID_TIMER 1
long FAR PASCAL WndProc (HWND, WORD, WORD, LONG) ;
int PASCAL WinMain (HANDLE hInstance, HANDLE hPrevInstance,
LPSTR lpszCmdLine, int nCmdShow)
{
static char szAppName[] = "Beeper1" ;
HWND hwnd ;
MSG msg ;
WNDCLASS wndclass ;
if (!hPrevInstance)
{
wndclass.style = CS_HREDRAW | CS_VREDRAW ;
wndclass.lpfnWndProc = WndProc ;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hInstance = hInstance ;
wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = GetStockObject (WHITE_BRUSH) ;
wndclass.lpszMenuName = NULL ;
wndclass.lpszClassName = szAppName ;
RegisterClass (&wndclass) ;
}
hwnd = CreateWindow (szAppName, "Beeper1 Timer Demo",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL) ;
while (!SetTimer (hwnd, ID_TIMER, 1000, NULL))
if (IDCANCEL == MessageBox (hwnd,
"Too many clocks or timers!", szAppName,
MB_ICONEXCLAMATION | MB_RETRYCANCEL))
return FALSE ;
ShowWindow (hwnd, nCmdShow) ;
UpdateWindow (hwnd) ;
while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
return msg.wParam ;
}
long FAR PASCAL WndProc (HWND hwnd, WORD message, WORD wParam, LONG lParam)
{
static BOOL fFlipFlop = FALSE ;
HBRUSH hBrush ;
HDC hdc ;
PAINTSTRUCT ps ;
RECT rc ;
switch (message)
{
case WM_TIMER:
MessageBeep (0) ;
fFlipFlop = !fFlipFlop ;
InvalidateRect (hwnd, NULL, FALSE) ;
return 0 ;
case WM_PAINT:
hdc = BeginPaint (hwnd, &ps) ;
GetClientRect (hwnd, &rc) ;
hBrush = CreateSolidBrush (fFlipFlop ? RGB(255,0,0) :
RGB(0,0,255)) ;
FillRect (hdc, &rc, hBrush) ;
EndPaint (hwnd, &ps) ;
DeleteObject (hBrush) ;
return 0 ;
case WM_DESTROY:
KillTimer (hwnd, ID_TIMER) ;
PostQuitMessage (0) ;
return 0 ;
}
return DefWindowProc (hwnd, message, wParam, lParam) ;
}
BEEPER2.C
CD-ROM Disc Path: \SAMPCODE\PROGWIN\CHAP05\BEEPER2.C
/*----------------------------------------
BEEPER2.C -- Timer Demo Program No. 2
(c) Charles Petzold, 1990
----------------------------------------*/
#include <windows.h>
#define ID_TIMER 1
long FAR PASCAL WndProc (HWND, WORD, WORD, LONG) ;
WORD FAR PASCAL TimerProc (HWND, WORD, WORD, LONG) ;
int PASCAL WinMain (HANDLE hInstance, HANDLE hPrevInstance,
LPSTR lpszCmdLine, int nCmdShow)
{
static char szAppName[] = "Beeper2" ;
FARPROC lpfnTimerProc ;
HWND hwnd ;
MSG msg ;
WNDCLASS wndclass ;
if (!hPrevInstance)
{
wndclass.style = CS_HREDRAW | CS_VREDRAW ;
wndclass.lpfnWndProc = WndProc ;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hInstance = hInstance ;
wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = GetStockObject (WHITE_BRUSH) ;
wndclass.lpszMenuName = NULL ;
wndclass.lpszClassName = szAppName ;
RegisterClass (&wndclass) ;
}
hwnd = CreateWindow (szAppName, "Beeper2 Timer Demo",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL) ;
lpfnTimerProc = MakeProcInstance (TimerProc, hInstance) ;
while (!SetTimer (hwnd, ID_TIMER, 1000, lpfnTimerProc))
if (IDCANCEL == MessageBox (hwnd,
"Too many clocks or timers!", szAppName,
MB_ICONEXCLAMATION | MB_RETRYCANCEL))
return FALSE ;
ShowWindow (hwnd, nCmdShow) ;
UpdateWindow (hwnd) ;
while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
return msg.wParam ;
}
long FAR PASCAL WndProc (HWND hwnd, WORD message, WORD wParam, LONG lParam)
{
switch (message)
{
case WM_DESTROY:
KillTimer (hwnd, ID_TIMER) ;
PostQuitMessage (0) ;
return 0 ;
}
return DefWindowProc (hwnd, message, wParam, lParam) ;
}
WORD FAR PASCAL TimerProc (HWND hwnd, WORD message, WORD wParam, LONG lParam)
{
static BOOL fFlipFlop = FALSE ;
HBRUSH hBrush ;
HDC hdc ;
RECT rc ;
MessageBeep (0) ;
fFlipFlop = !fFlipFlop ;
GetClientRect (hwnd, &rc) ;
hdc = GetDC (hwnd) ;
hBrush = CreateSolidBrush (fFlipFlop ? RGB(255,0,0) : RGB(0,0,255)) ;
FillRect (hdc, &rc, hBrush) ;
ReleaseDC (hwnd, hdc) ;
DeleteObject (hBrush) ;
return 0 ;
}
BITLIB.C
CD-ROM Disc Path: \SAMPCODE\PROGWIN\CHAP19\BITLIB.C
/*--------------------------------------------------------------
BITLIB.C -- Code entry point for BITLIB dynamic link library
(c) Charles Petzold, 1990
--------------------------------------------------------------*/
#include <windows.h>
int FAR PASCAL LibMain (HANDLE hInstance, WORD wDataSeg, WORD wHeapSize,
LPSTR lpszCmdLine)
{
if (wHeapSize > 0)
UnlockData (0) ;
return 1 ;
}
BLOWUP1.C
CD-ROM Disc Path: \SAMPCODE\PROGWIN\CHAP04\BLOWUP1.C
/*------------------------------------------------
BLOWUP1.C -- Screen Capture Mouse Demo Program
(c) Charles Petzold, 1990
------------------------------------------------*/
#include <windows.h>
long FAR PASCAL WndProc (HWND, WORD, WORD, LONG) ;
int PASCAL WinMain (HANDLE hInstance, HANDLE hPrevInstance,
LPSTR lpszCmdLine, int nCmdShow)
{
static char szAppName[] = "BlowUp1" ;
HWND hwnd ;
MSG msg ;
WNDCLASS wndclass ;
if (!hPrevInstance)
{
wndclass.style = CS_HREDRAW | CS_VREDRAW ;
wndclass.lpfnWndProc = WndProc ;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hInstance = hInstance ;
wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = GetStockObject (WHITE_BRUSH) ;
wndclass.lpszMenuName = NULL ;
wndclass.lpszClassName = szAppName ;
RegisterClass (&wndclass) ;
}
hwnd = CreateWindow (szAppName, "Blow-Up Mouse Demo",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL) ;
ShowWindow (hwnd, nCmdShow) ;
UpdateWindow (hwnd) ;
while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
return msg.wParam ;
}
void InvertBlock (HWND hwnd, POINT ptBeg, POINT ptEnd)
{
HDC hdc ;
hdc = CreateDC ("DISPLAY", NULL, NULL, NULL) ;
ClientToScreen (hwnd, &ptBeg) ;
ClientToScreen (hwnd, &ptEnd) ;
PatBlt (hdc, ptBeg.x, ptBeg.y, ptEnd.x - ptBeg.x, ptEnd.y - ptBeg.y,
DSTINVERT) ;
DeleteDC (hdc) ;
}
long FAR PASCAL WndProc (HWND hwnd, WORD message, WORD wParam, LONG lParam)
{
static BOOL fCapturing, fBlocking ;
static POINT ptBeg, ptEnd ;
HDC hdc ;
RECT rect ;
switch (message)
{
case WM_LBUTTONDOWN:
if (!fCapturing)
{
fCapturing = TRUE ;
SetCapture (hwnd) ;
SetCursor (LoadCursor (NULL, IDC_CROSS)) ;
}
else if (!fBlocking)
{
fBlocking = TRUE ;
ptBeg = MAKEPOINT (lParam) ;
}
return 0 ;
case WM_MOUSEMOVE:
if (fBlocking)
{
ptEnd = MAKEPOINT (lParam) ;
InvertBlock (hwnd, ptBeg, ptEnd) ;
InvertBlock (hwnd, ptBeg, ptEnd) ;
}
return 0 ;
case WM_LBUTTONUP:
if (fBlocking)
{
fCapturing = fBlocking = FALSE ;
ptEnd = MAKEPOINT (lParam) ;
SetCursor (LoadCursor (NULL, IDC_WAIT)) ;
hdc = GetDC (hwnd) ;
GetClientRect (hwnd, &rect) ;
StretchBlt (hdc, 0, 0, rect.right, rect.bottom,
hdc, ptBeg.x, ptBeg.y,
ptEnd.x - ptBeg.x, ptEnd.y - ptBeg.y,
SRCCOPY) ;
ReleaseDC (hwnd, hdc) ;
SetCursor (LoadCursor (NULL, IDC_ARROW)) ;
ReleaseCapture () ;
}
return 0 ;
case WM_DESTROY:
PostQuitMessage (0) ;
return 0 ;
}
return DefWindowProc (hwnd, message, wParam, lParam) ;
}
BLOWUP2.C
CD-ROM Disc Path: \SAMPCODE\PROGWIN\CHAP16\BLOWUP2.C
/*------------------------------------------------
BLOWUP2.C -- Capture Screen Image to Clipboard
(c) Charles Petzold, 1990
------------------------------------------------*/
#include <windows.h>
#include <stdlib.h>
long FAR PASCAL WndProc (HWND, WORD, WORD, LONG) ;
int PASCAL WinMain (HANDLE hInstance, HANDLE hPrevInstance,
LPSTR lpszCmdLine, int nCmdShow)
{
static char szAppName [] = "Blowup2" ;
HWND hwnd ;
MSG msg ;
WNDCLASS wndclass ;
if (!hPrevInstance)
{
wndclass.style = CS_HREDRAW | CS_VREDRAW ;
wndclass.lpfnWndProc = WndProc ;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hInstance = hInstance ;
wndclass.hIcon = NULL ;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = GetStockObject (WHITE_BRUSH) ;
wndclass.lpszMenuName = NULL ;
wndclass.lpszClassName = szAppName ;
RegisterClass (&wndclass) ;
}
hwnd = CreateWindow (szAppName, szAppName,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL) ;
ShowWindow (hwnd, nCmdShow) ;
UpdateWindow (hwnd) ;
while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
return msg.wParam ;
}
void InvertBlock (HWND hwnd, POINT org, POINT len)
{
HDC hdc ;
hdc = CreateDC ("DISPLAY", NULL, NULL, NULL) ;
ClientToScreen (hwnd, &org) ;
PatBlt (hdc, org.x, org.y, len.x, len.y, DSTINVERT) ;
DeleteDC (hdc) ;
}
long FAR PASCAL WndProc (HWND hwnd, WORD message, WORD wParam, LONG lParam)
{
static BOOL bCapturing, bBlocking ;
static POINT org, len ;
static short cxClient, cyClient ;
BITMAP bm ;
HDC hdc, hdcMem ;
HBITMAP hBitmap ;
PAINTSTRUCT ps ;
switch (message)
{
case WM_SIZE:
cxClient = LOWORD (lParam) ;
cyClient = HIWORD (lParam) ;
return 0 ;
case WM_LBUTTONDOWN:
if (!bCapturing)
{
bCapturing = TRUE ;
SetCapture (hwnd) ;
SetCursor (LoadCursor (NULL, IDC_CROSS)) ;
}
else if (!bBlocking)
{
bBlocking = TRUE ;
org = MAKEPOINT (lParam) ;
}
return 0 ;
case WM_MOUSEMOVE:
if (bCapturing)
SetCursor (LoadCursor (NULL, IDC_CROSS)) ;
if (bBlocking)
{
len = MAKEPOINT (lParam) ;
len.x -= org.x ;
len.y -= org.y ;
InvertBlock (hwnd, org, len) ;
InvertBlock (hwnd, org, len) ;
}
return 0 ;
case WM_LBUTTONUP:
if (!bBlocking)
break ;
bCapturing = bBlocking = FALSE ;
SetCursor (LoadCursor (NULL, IDC_ARROW)) ;
ReleaseCapture () ;
if (len.x == 0 || len.y == 0)
break ;
hdc = GetDC (hwnd) ;
hdcMem = CreateCompatibleDC (hdc) ;
hBitmap = CreateCompatibleBitmap (hdc,
abs (len.x), abs (len.y)) ;
if (hBitmap)
{
SelectObject (hdcMem, hBitmap) ;
StretchBlt (hdcMem, 0, 0, abs (len.x), abs (len.y),
hdc, org.x, org.y, len.x, len.y, SRCCOPY) ;
OpenClipboard (hwnd) ;
EmptyClipboard () ;
SetClipboardData (CF_BITMAP, hBitmap) ;
CloseClipboard () ;
InvalidateRect (hwnd, NULL, TRUE) ;
}
else
MessageBeep (0) ;
DeleteDC (hdcMem) ;
ReleaseDC (hwnd, hdc) ;
return 0 ;
case WM_PAINT:
InvalidateRect (hwnd, NULL, TRUE) ;
hdc = BeginPaint (hwnd, &ps) ;
OpenClipboard (hwnd) ;
if (hBitmap = GetClipboardData (CF_BITMAP))
{
SetCursor (LoadCursor (NULL, IDC_WAIT)) ;
hdcMem = CreateCompatibleDC (hdc) ;
SelectObject (hdcMem, hBitmap) ;
GetObject (hBitmap, sizeof (BITMAP), (LPSTR) &bm) ;
SetStretchBltMode (hdc, COLORONCOLOR) ;
StretchBlt (hdc, 0, 0, cxClient, cyClient,
hdcMem, 0, 0, bm.bmWidth, bm.bmHeight,
SRCCOPY) ;
SetCursor (LoadCursor (NULL, IDC_ARROW)) ;
DeleteDC (hdcMem) ;
}
CloseClipboard () ;
EndPaint (hwnd, &ps) ;
return 0 ;
case WM_DESTROY:
PostQuitMessage (0) ;
return 0 ;
}
return DefWindowProc (hwnd, message, wParam, lParam) ;
}
BOUNCE.C
CD-ROM Disc Path: \SAMPCODE\PROGWIN\CHAP13\BOUNCE.C
/*---------------------------------------
BOUNCE.C -- Bouncing Ball Program
(c) Charles Petzold, 1990
---------------------------------------*/
#include <windows.h>
long FAR PASCAL WndProc (HWND, WORD, WORD, LONG) ;
int PASCAL WinMain (HANDLE hInstance, HANDLE hPrevInstance,
LPSTR lpszCmdLine, int nCmdShow)
{
static char szAppName [] = "Bounce" ;
HWND hwnd ;
MSG msg ;
WNDCLASS wndclass ;
if (!hPrevInstance)
{
wndclass.style = CS_HREDRAW | CS_VREDRAW ;
wndclass.lpfnWndProc = WndProc ;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hInstance = hInstance ;
wndclass.hIcon = NULL ;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = GetStockObject (WHITE_BRUSH) ;
wndclass.lpszMenuName = NULL ;
wndclass.lpszClassName = szAppName ;
RegisterClass (&wndclass) ;
}
hwnd = CreateWindow (szAppName, "Bouncing Ball",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL) ;
if (!SetTimer (hwnd, 1, 50, NULL))
{
MessageBox (hwnd, "Too many clocks or timers!",
szAppName, MB_ICONEXCLAMATION | MB_OK) ;
return FALSE ;
}
ShowWindow (hwnd, nCmdShow) ;
UpdateWindow (hwnd) ;
while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
return msg.wParam ;
}
long FAR PASCAL WndProc (HWND hwnd, WORD message, WORD wParam, LONG lParam)
{
static HANDLE hBitmap ;
static short cxClient, cyClient, xCenter, yCenter, cxTotal, cyTotal,
cxRadius, cyRadius, cxMove, cyMove, xPixel, yPixel ;
HBRUSH hBrush ;
HDC hdc, hdcMem ;
short nScale ;
switch (message)
{
case WM_CREATE:
hdc = GetDC (hwnd) ;
xPixel = GetDeviceCaps (hdc, ASPECTX) ;
yPixel = GetDeviceCaps (hdc, ASPECTY) ;
ReleaseDC (hwnd, hdc) ;
return 0 ;
case WM_SIZE:
xCenter = (cxClient = LOWORD (lParam)) / 2 ;
yCenter = (cyClient = HIWORD (lParam)) / 2 ;
nScale = min (cxClient * xPixel, cyClient * yPixel) / 16 ;
cxRadius = nScale / xPixel ;
cyRadius = nScale / yPixel ;
cxMove = max (1, cxRadius / 4) ;
cyMove = max (1, cyRadius / 4) ;
cxTotal = 2 * (cxRadius + cxMove) ;
cyTotal = 2 * (cyRadius + cyMove) ;
if (hBitmap)
DeleteObject (hBitmap) ;
hdc = GetDC (hwnd) ;
hdcMem = CreateCompatibleDC (hdc) ;
hBitmap = CreateCompatibleBitmap (hdc, cxTotal, cyTotal) ;
ReleaseDC (hwnd, hdc) ;
SelectObject (hdcMem, hBitmap) ;
Rectangle (hdcMem, -1, -1, cxTotal + 1, cyTotal + 1) ;
hBrush = CreateHatchBrush (HS_DIAGCROSS, 0L) ;
SelectObject (hdcMem, hBrush) ;
SetBkColor (hdcMem, RGB (255, 0, 255)) ;
Ellipse (hdcMem, cxMove, cyMove, cxTotal - cxMove,
cyTotal - cyMove) ;
DeleteDC (hdcMem) ;
DeleteObject (hBrush) ;
return 0 ;
case WM_TIMER:
if (!hBitmap)
break ;
hdc = GetDC (hwnd) ;
hdcMem = CreateCompatibleDC (hdc) ;
SelectObject (hdcMem, hBitmap) ;
BitBlt (hdc, xCenter - cxTotal / 2,
yCenter - cyTotal / 2, cxTotal, cyTotal,
hdcMem, 0, 0, SRCCOPY) ;
ReleaseDC (hwnd, hdc) ;
DeleteDC (hdcMem) ;
xCenter += cxMove ;
yCenter += cyMove ;
if ((xCenter + cxRadius >= cxClient) ||
(xCenter - cxRadius <= 0))
cxMove = -cxMove ;
if ((yCenter + cyRadius >= cyClient) ||
(yCenter - cyRadius <= 0))
cyMove = -cyMove ;
return 0 ;
case WM_DESTROY:
if (hBitmap)
DeleteObject (hBitmap) ;
KillTimer (hwnd, 1) ;
PostQuitMessage (0) ;
return 0 ;
}
return DefWindowProc (hwnd, message, wParam, lParam) ;
}
BTNLOOK.C
CD-ROM Disc Path: \SAMPCODE\PROGWIN\CHAP06\BTNLOOK.C
/*----------------------------------------
BTNLOOK.C -- Button Look Program
(c) Charles Petzold, 1990
----------------------------------------*/
#include <windows.h>
#include <stdio.h>
struct
{
long style ;
char *text ;
}
button[] =
{
BS_PUSHBUTTON, "PUSHBUTTON",
BS_DEFPUSHBUTTON, "DEFPUSHBUTTON",
BS_CHECKBOX, "CHECKBOX",
BS_AUTOCHECKBOX, "AUTOCHECKBOX",
BS_RADIOBUTTON, "RADIOBUTTON",
BS_3STATE, "3STATE",
BS_AUTO3STATE, "AUTO3STATE",
BS_GROUPBOX, "GROUPBOX",
BS_USERBUTTON, "USERBUTTON",
BS_AUTORADIOBUTTON, "AUTORADIO",
BS_PUSHBOX, "PUSHBOX"
} ;
#define NUM (sizeof button / sizeof button [0])
long FAR PASCAL WndProc (HWND, WORD, WORD, LONG) ;
int PASCAL WinMain (HANDLE hInstance, HANDLE hPrevInstance,
LPSTR lpszCmdLine, int nCmdShow)
{
static char szAppName[] = "BtnLook" ;
HWND hwnd ;
MSG msg ;
WNDCLASS wndclass ;
if (!hPrevInstance)
{
wndclass.style = CS_HREDRAW | CS_VREDRAW ;
wndclass.lpfnWndProc = WndProc ;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hInstance = hInstance ;
wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = GetStockObject (WHITE_BRUSH) ;
wndclass.lpszMenuName = NULL ;
wndclass.lpszClassName = szAppName ;
RegisterClass (&wndclass) ;
}
hwnd = CreateWindow (szAppName, "Button Look",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL) ;
ShowWindow (hwnd, nCmdShow) ;
UpdateWindow (hwnd) ;
while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
return msg.wParam ;
}
long FAR PASCAL WndProc (HWND hwnd, WORD message, WORD wParam, LONG lParam)
{
static char szPrm [] = "wParam LOWORD(lParam) HIWORD(lParam)"
szTop [] = "Control ID Window Handle Notification",
szUnd [] = "__________ _____________ ____________",
szFormat [] = " %5u %4X %5u",
szBuffer [50] ;
static HWND hwndButton [NUM] ;
static RECT rect ;
static int cxChar, cyChar ;
HDC hdc ;
PAINTSTRUCT ps ;
int i ;
TEXTMETRIC tm ;
switch (message)
{
case WM_CREATE:
hdc = GetDC (hwnd) ;
SelectObject (hdc, GetStockObject (SYSTEM_FIXED_FONT)) ;
GetTextMetrics (hdc, &tm) ;
cxChar = tm.tmAveCharWidth ;
cyChar = tm.tmHeight + tm.tmExternalLeading ;
ReleaseDC (hwnd, hdc) ;
for (i = 0 ; i < NUM ; i++)
hwndButton [i] = CreateWindow ("button", button[i].text,
WS_CHILD | WS_VISIBLE | button[i].style,
cxChar, cyChar * (1 + 2 * i),
20 * cxChar, 7 * cyChar / 4,
hwnd, i,
((LPCREATESTRUCT) lParam) -> hInstance, NULL) ;
return 0 ;
case WM_SIZE:
rect.left = 24 * cxChar ;
rect.top = 3 * cyChar ;
rect.right = LOWORD (lParam) ;
rect.bottom = HIWORD (lParam) ;
return 0 ;
case WM_PAINT:
InvalidateRect (hwnd, &rect, TRUE) ;
hdc = BeginPaint (hwnd, &ps) ;
SelectObject (hdc, GetStockObject (SYSTEM_FIXED_FONT)) ;
SetBkMode (hdc, TRANSPARENT) ;
TextOut (hdc, 24 * cxChar, 1 * cyChar, szPrm, sizeof szPrm - 1
TextOut (hdc, 24 * cxChar, 2 * cyChar, szTop, sizeof szTop - 1
TextOut (hdc, 24 * cxChar, 2 * cyChar, szUnd, sizeof szUnd - 1
EndPaint (hwnd, &ps) ;
return 0 ;
case WM_COMMAND:
ScrollWindow (hwnd, 0, -cyChar, &rect, &rect) ;
hdc = GetDC (hwnd) ;
SelectObject (hdc, GetStockObject (SYSTEM_FIXED_FONT)) ;
TextOut (hdc, 24 * cxChar, cyChar * (rect.bottom / cyChar - 1)
szBuffer, sprintf (szBuffer, szFormat, wParam,
LOWORD (lParam), HIWORD (lParam))) ;
ReleaseDC (hwnd, hdc) ;
ValidateRect (hwnd, NULL) ;
return 0 ;
case WM_DESTROY:
PostQuitMessage (0) ;
return 0 ;
}
return DefWindowProc (hwnd, message, wParam, lParam) ;
}
CHECKER1.C
CD-ROM Disc Path: \SAMPCODE\PROGWIN\CHAP04\CHECKER1.C
/*-------------------------------------------------
CHECKER1.C -- Mouse Hit-Test Demo Program No. 1
(c) Charles Petzold, 1990
-------------------------------------------------*/
#include <windows.h>
#define DIVISIONS 5
long FAR PASCAL WndProc (HWND, WORD, WORD, LONG) ;
int PASCAL WinMain (HANDLE hInstance, HANDLE hPrevInstance,
LPSTR lpszCmdLine, int nCmdShow)
{
static char szAppName[] = "Checker1" ;
HWND hwnd ;
MSG msg ;
WNDCLASS wndclass ;
if (!hPrevInstance)
{
wndclass.style = CS_HREDRAW | CS_VREDRAW ;
wndclass.lpfnWndProc = WndProc ;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hInstance = hInstance ;
wndclass.hIcon = NULL ;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = GetStockObject (WHITE_BRUSH) ;
wndclass.lpszMenuName = NULL ;
wndclass.lpszClassName = szAppName ;
RegisterClass (&wndclass) ;
}
hwnd = CreateWindow (szAppName, "Checker1 Mouse Hit-Test Demo",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL) ;
ShowWindow (hwnd, nCmdShow) ;
UpdateWindow (hwnd) ;
while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
return msg.wParam ;
}
long FAR PASCAL WndProc (HWND hwnd, WORD message, WORD wParam, LONG lParam)
{
static BOOL fState[DIVISIONS][DIVISIONS] ;
static short cxBlock, cyBlock ;
HDC hdc ;
PAINTSTRUCT ps ;
RECT rect ;
short x, y ;
switch (message)
{
case WM_SIZE:
cxBlock = LOWORD (lParam) / DIVISIONS ;
cyBlock = HIWORD (lParam) / DIVISIONS ;
return 0 ;
case WM_LBUTTONDOWN:
x = LOWORD (lParam) / cxBlock ;
y = HIWORD (lParam) / cyBlock ;
if (x < DIVISIONS && y < DIVISIONS)
{
fState [x][y] ^= 1 ;
rect.left = x * cxBlock ;
rect.top = y * cyBlock ;
rect.right = (x + 1) * cxBlock ;
rect.bottom = (y + 1) * cyBlock ;
InvalidateRect (hwnd, &rect, FALSE) ;
}
else
MessageBeep (0) ;
return 0 ;
case WM_PAINT:
hdc = BeginPaint (hwnd, &ps) ;
for (x = 0 ; x < DIVISIONS ; x++)
for (y = 0 ; y < DIVISIONS ; y++)
{
Rectangle (hdc, x * cxBlock, y * cyBlock,
(x + 1) * cxBlock, (y + 1) * cyBlock) ;
if (fState [x][y])
{
MoveTo (hdc, x * cxBlock, y * cyBlock)
LineTo (hdc, (x+1) * cxBlock, (y+1) * cyBlock)
MoveTo (hdc, x * cxBlock, (y+1) * cyBlock)
LineTo (hdc, (x+1) * cxBlock, y * cyBlock)
}
}
EndPaint (hwnd, &ps) ;
return 0 ;
case WM_DESTROY:
PostQuitMessage (0) ;
return 0 ;
}
return DefWindowProc (hwnd, message, wParam, lParam) ;
}
CHECKER2.C
CD-ROM Disc Path: \SAMPCODE\PROGWIN\CHAP04\CHECKER2.C
/*-------------------------------------------------
CHECKER2.C -- Mouse Hit-Test Demo Program No. 2
(c) Charles Petzold, 1990
-------------------------------------------------*/
#include <windows.h>
#define DIVISIONS 5
long FAR PASCAL WndProc (HWND, WORD, WORD, LONG) ;
int PASCAL WinMain (HANDLE hInstance, HANDLE hPrevInstance,
LPSTR lpszCmdLine, int nCmdShow)
{
static char szAppName[] = "Checker2" ;
HWND hwnd ;
MSG msg ;
WNDCLASS wndclass ;
if (!hPrevInstance)
{
wndclass.style = CS_HREDRAW | CS_VREDRAW ;
wndclass.lpfnWndProc = WndProc ;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hInstance = hInstance ;
wndclass.hIcon = NULL ;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = GetStockObject (WHITE_BRUSH) ;
wndclass.lpszMenuName = NULL ;
wndclass.lpszClassName = szAppName ;
RegisterClass (&wndclass) ;
}
hwnd = CreateWindow (szAppName, "Checker2 Mouse Hit-Test Demo",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL) ;
ShowWindow (hwnd, nCmdShow) ;
UpdateWindow (hwnd) ;
while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
return msg.wParam ;
}
long FAR PASCAL WndProc (HWND hwnd, WORD message, WORD wParam, LONG lParam)
{
static BOOL fState[DIVISIONS][DIVISIONS] ;
static short cxBlock, cyBlock ;
HDC hdc ;
PAINTSTRUCT ps ;
POINT point ;
RECT rect ;
short x, y ;
switch (message)
{
case WM_SIZE:
cxBlock = LOWORD (lParam) / DIVISIONS ;
cyBlock = HIWORD (lParam) / DIVISIONS ;
return 0 ;
case WM_SETFOCUS:
ShowCursor (TRUE) ;
return 0 ;
case WM_KILLFOCUS:
ShowCursor (FALSE) ;
return 0 ;
case WM_KEYDOWN:
GetCursorPos (&point) ;
ScreenToClient (hwnd, &point) ;
x = max (0, min (DIVISIONS - 1, point.x / cxBlock)) ;
y = max (0, min (DIVISIONS - 1, point.y / cyBlock)) ;
switch (wParam)
{
case VK_UP:
y -- ;
break ;
case VK_DOWN:
y ++ ;
break ;
case VK_LEFT:
x -- ;
break ;
case VK_RIGHT:
x ++ ;
break ;
case VK_HOME:
x = y = 0 ;
break ;
case VK_END:
x = y = DIVISIONS - 1 ;
break ;
case VK_RETURN:
case VK_SPACE:
SendMessage (hwnd, WM_LBUTTONDOWN, MK_LBUTTON,
MAKELONG (x * cxBlock, y * cyBlock)) ;
break ;
}
x = (x + DIVISIONS) % DIVISIONS ;
y = (y + DIVISIONS) % DIVISIONS ;
point.x = x * cxBlock + cxBlock / 2 ;
point.y = y * cyBlock + cyBlock / 2 ;
ClientToScreen (hwnd, &point) ;
SetCursorPos (point.x, point.y) ;
return 0 ;
case WM_LBUTTONDOWN:
x = LOWORD (lParam) / cxBlock ;
y = HIWORD (lParam) / cyBlock ;
if (x < DIVISIONS && y < DIVISIONS)
{
fState[x][y] ^= 1 ;
rect.left = x * cxBlock ;
rect.top = y * cyBlock ;
rect.right = (x + 1) * cxBlock ;
rect.bottom = (y + 1) * cyBlock ;
InvalidateRect (hwnd, &rect, FALSE) ;
}
else
MessageBeep (0) ;
return 0 ;
case WM_PAINT:
hdc = BeginPaint (hwnd, &ps) ;
for (x = 0 ; x < DIVISIONS ; x++)
for (y = 0 ; y < DIVISIONS ; y++)
{
Rectangle (hdc, x * cxBlock, y * cyBlock,
(x + 1) * cxBlock, (y + 1) * cyBlock) ;
if (fState [x][y])
{
MoveTo (hdc, x * cxBlock, y * cyBlock)
LineTo (hdc, (x+1) * cxBlock, (y+1) * cyBlock)
MoveTo (hdc, x * cxBlock, (y+1) * cyBlock)
LineTo (hdc, (x+1) * cxBlock, y * cyBlock)
}
}
EndPaint (hwnd, &ps) ;
return 0 ;
case WM_DESTROY:
PostQuitMessage (0) ;
return 0 ;
}
return DefWindowProc (hwnd, message, wParam, lParam) ;
}
CHECKER3.C
CD-ROM Disc Path: \SAMPCODE\PROGWIN\CHAP04\CHECKER3.C
/*-------------------------------------------------
CHECKER3.C -- Mouse Hit-Test Demo Program No. 3
(c) Charles Petzold, 1990
-------------------------------------------------*/
#include <windows.h>
#define DIVISIONS 5
long FAR PASCAL WndProc (HWND, WORD, WORD, LONG) ;
long FAR PASCAL ChildWndProc (HWND, WORD, WORD, LONG) ;
char szChildClass[] = "Checker3_Child" ;
int PASCAL WinMain (HANDLE hInstance, HANDLE hPrevInstance,
LPSTR lpszCmdLine, int nCmdShow)
{
static char szAppName[] = "Checker3" ;
HWND hwnd ;
MSG msg ;
WNDCLASS wndclass ;
if (!hPrevInstance)
{
wndclass.style = CS_HREDRAW | CS_VREDRAW ;
wndclass.lpfnWndProc = WndProc ;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hInstance = hInstance ;
wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = GetStockObject (WHITE_BRUSH) ;
wndclass.lpszMenuName = NULL ;
wndclass.lpszClassName = szAppName ;
RegisterClass (&wndclass) ;
wndclass.lpfnWndProc = ChildWndProc ;
wndclass.cbWndExtra = sizeof (WORD) ;
wndclass.hIcon = NULL ;
wndclass.lpszClassName = szChildClass ;
RegisterClass (&wndclass) ;
}
hwnd = CreateWindow (szAppName, "Checker3 Mouse Hit-Test Demo",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL) ;
ShowWindow (hwnd, nCmdShow) ;
UpdateWindow (hwnd) ;
while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
return msg.wParam ;
}
long FAR PASCAL WndProc (HWND hwnd, WORD message, WORD wParam, LONG lParam)
{
static HWND hwndChild [DIVISIONS] [DIVISIONS] ;
short cxBlock, cyBlock, x, y ;
switch (message)
{
case WM_CREATE:
for (x = 0 ; x < DIVISIONS ; x++)
for (y = 0 ; y < DIVISIONS ; y++)
{
hwndChild [x][y] = CreateWindow (szChildClass, NULL,
WS_CHILDWINDOW | WS_VISIBLE,
0, 0, 0, 0,
hwnd, y << 8 | x,
GetWindowWord (hwnd, GWW_HINSTANCE), NULL) ;
}
return 0 ;
case WM_SIZE:
cxBlock = LOWORD (lParam) / DIVISIONS ;
cyBlock = HIWORD (lParam) / DIVISIONS ;
for (x = 0 ; x < DIVISIONS ; x++)
for (y = 0 ; y < DIVISIONS ; y++)
MoveWindow (hwndChild [x][y],
x * cxBlock, y * cyBlock,
cxBlock, cyBlock, TRUE) ;
return 0 ;
case WM_LBUTTONDOWN:
MessageBeep (0) ;
return 0 ;
case WM_DESTROY:
PostQuitMessage (0) ;
return 0 ;
}
return DefWindowProc (hwnd, message, wParam, lParam) ;
}
long FAR PASCAL ChildWndProc (HWND hwnd, WORD message, WORD wParam, LONG lPar
{
HDC hdc ;
PAINTSTRUCT ps ;
RECT rect ;
switch (message)
{
case WM_CREATE:
SetWindowWord (hwnd, 0, 0) ; // on/off flag
return 0 ;
case WM_LBUTTONDOWN:
SetWindowWord (hwnd, 0, 1 ^ GetWindowWord (hwnd, 0)) ;
InvalidateRect (hwnd, NULL, FALSE) ;
return 0 ;
case WM_PAINT:
hdc = BeginPaint (hwnd, &ps) ;
GetClientRect (hwnd, &rect) ;
Rectangle (hdc, 0, 0, rect.right, rect.bottom) ;
if (GetWindowWord (hwnd, 0))
{
MoveTo (hdc, 0, 0) ;
LineTo (hdc, rect.right, rect.bottom) ;
MoveTo (hdc, 0, rect.bottom) ;
LineTo (hdc, rect.right, 0) ;
}
EndPaint (hwnd, &ps) ;
return 0 ;
}
return DefWindowProc (hwnd, message, wParam, lParam) ;
}
CLIPVIEW.C
CD-ROM Disc Path: \SAMPCODE\PROGWIN\CHAP16\CLIPVIEW.C
/*-----------------------------------------
CLIPVIEW.C -- Simple Clipboard Viewer
(c) Charles Petzold, 1990
-----------------------------------------*/
#include <windows.h>
long FAR PASCAL WndProc (HWND, WORD, WORD, LONG) ;
int PASCAL WinMain (HANDLE hInstance, HANDLE hPrevInstance,
LPSTR lpszCmdLine, int nCmdShow)
{
static char szAppName [] = "ClipView" ;
HWND hwnd ;
MSG msg ;
WNDCLASS wndclass ;
if (!hPrevInstance)
{
wndclass.style = CS_HREDRAW | CS_VREDRAW ;
wndclass.lpfnWndProc = WndProc ;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hInstance = hInstance ;
wndclass.hIcon = NULL ;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = GetStockObject (WHITE_BRUSH) ;
wndclass.lpszMenuName = NULL ;
wndclass.lpszClassName = szAppName ;
RegisterClass (&wndclass) ;
}
hwnd = CreateWindow (szAppName, "Simple Clipboard Viewer (Text Only)",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL) ;
ShowWindow (hwnd, nCmdShow) ;
UpdateWindow (hwnd) ;
while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
return msg.wParam ;
}
long FAR PASCAL WndProc (HWND hwnd, WORD message, WORD wParam, LONG lParam)
{
static HWND hwndNextViewer ;
HANDLE hGMem ;
HDC hdc ;
LPSTR lpGMem ;
PAINTSTRUCT ps ;
RECT rect ;
switch (message)
{
case WM_CREATE:
hwndNextViewer = SetClipboardViewer (hwnd) ;
return 0 ;
case WM_CHANGECBCHAIN :
if (wParam == hwndNextViewer)
hwndNextViewer = LOWORD (lParam) ;
else if (hwndNextViewer)
SendMessage (hwndNextViewer, message, wParam, lParam) ;
return 0 ;
case WM_DRAWCLIPBOARD :
if (hwndNextViewer)
SendMessage (hwndNextViewer, message, wParam, lParam) ;
InvalidateRect (hwnd, NULL, TRUE) ;
return 0 ;
case WM_PAINT:
hdc = BeginPaint (hwnd, &ps) ;
GetClientRect (hwnd, &rect) ;
OpenClipboard (hwnd) ;
if (hGMem = GetClipboardData (CF_TEXT))
{
lpGMem = GlobalLock (hGMem) ;
DrawText (hdc, lpGMem, -1, &rect, DT_EXPANDTABS) ;
GlobalUnlock (hGMem) ;
}
CloseClipboard () ;
EndPaint (hwnd, &ps) ;
return 0 ;
case WM_DESTROY:
ChangeClipboardChain (hwnd, hwndNextViewer) ;
PostQuitMessage (0) ;
return 0 ;
}
return DefWindowProc (hwnd, message, wParam, lParam) ;
}
CLOVER.C
CD-ROM Disc Path: \SAMPCODE\PROGWIN\CHAP12\CLOVER.C
/*--------------------------------------------------
CLOVER.C -- Clover Drawing Program using Regions
(c) Charles Petzold, 1990
--------------------------------------------------*/
#include <windows.h>
#include <math.h>
#define TWO_PI (2.0 * 3.14159)
long FAR PASCAL WndProc (HWND, WORD, WORD, LONG) ;
int PASCAL WinMain (HANDLE hInstance, HANDLE hPrevInstance,
LPSTR lpszCmdLine, int nCmdShow)
{
static char szAppName[] = "Clover" ;
HWND hwnd ;
MSG msg ;
WNDCLASS wndclass ;
if (!hPrevInstance)
{
wndclass.style = CS_HREDRAW | CS_VREDRAW ;
wndclass.lpfnWndProc = WndProc ;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hInstance = hInstance ;
wndclass.hIcon = NULL ;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = GetStockObject (WHITE_BRUSH) ;
wndclass.lpszMenuName = NULL ;
wndclass.lpszClassName = szAppName ;
RegisterClass (&wndclass) ;
}
hwnd = CreateWindow (szAppName, "Draw a Clover",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL) ;
ShowWindow (hwnd, nCmdShow) ;
UpdateWindow (hwnd) ;
while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
return msg.wParam ;
}
long FAR PASCAL WndProc (HWND hwnd, WORD message, WORD wParam, LONG lParam)
{
static HRGN hRgnClip ;
static short cxClient, cyClient ;
double fAngle, fRadius ;
HCURSOR hCursor ;
HDC hdc ;
HRGN hRgnTemp [6] ;
PAINTSTRUCT ps ;
short i ;
switch (message)
{
case WM_SIZE:
cxClient = LOWORD (lParam) ;
cyClient = HIWORD (lParam) ;
hCursor = SetCursor (LoadCursor (NULL, IDC_WAIT)) ;
ShowCursor (TRUE) ;
if (hRgnClip)
DeleteObject (hRgnClip) ;
hRgnTemp [0] = CreateEllipticRgn (0, cyClient / 3,
cxClient / 2, 2 * cyClient / 3) ;
hRgnTemp [1] = CreateEllipticRgn (cxClient / 2, cyClient / 3,
cxClient, 2 * cyClient / 3) ;
hRgnTemp [2] = CreateEllipticRgn (cxClient / 3, 0,
2 * cxClient / 3, cyClient / 2) ;
hRgnTemp [3] = CreateEllipticRgn (cxClient / 3, cyClient / 2,
2 * cxClient / 3, cyClient) ;
hRgnTemp [4] = CreateRectRgn (0, 0, 1, 1) ;
hRgnTemp [5] = CreateRectRgn (0, 0, 1, 1) ;
hRgnClip = CreateRectRgn (0, 0, 1, 1) ;
CombineRgn (hRgnTemp [4], hRgnTemp [0], hRgnTemp [1], RGN_OR)
CombineRgn (hRgnTemp [5], hRgnTemp [2], hRgnTemp [3], RGN_OR)
CombineRgn (hRgnClip, hRgnTemp [4], hRgnTemp [5], RGN_XOR)
for (i = 0 ; i < 6 ; i++)
DeleteObject (hRgnTemp [i]) ;
SetCursor (hCursor) ;
ShowCursor (FALSE) ;
return 0 ;
case WM_PAINT:
hdc = BeginPaint (hwnd, &ps) ;
SetViewportOrg (hdc, cxClient / 2, cyClient / 2) ;
SelectClipRgn (hdc, hRgnClip) ;
fRadius = hypot (cxClient / 2.0, cyClient / 2.0) ;
for (fAngle = 0.0 ; fAngle < TWO_PI ; fAngle += TWO_PI / 360)
{
MoveTo (hdc, 0, 0) ;
LineTo (hdc, (short) ( fRadius * cos (fAngle) + 0.5),
(short) (-fRadius * sin (fAngle) + 0.5)) ;
}
EndPaint (hwnd, &ps) ;
return 0 ;
case WM_DESTROY:
DeleteObject (hRgnClip) ;
PostQuitMessage (0) ;
return 0 ;
}
return DefWindowProc (hwnd, message, wParam, lParam) ;
}
COLORS1.C
CD-ROM Disc Path: \SAMPCODE\PROGWIN\CHAP06\COLORS1.C
/*----------------------------------------
COLORS1.C -- Colors Using Scroll Bars
(c) Charles Petzold, 1990
----------------------------------------*/
#include <windows.h>
#include <stdlib.h>
long FAR PASCAL WndProc (HWND, WORD, WORD, LONG) ;
long FAR PASCAL ScrollProc (HWND, WORD, WORD, LONG) ;
FARPROC lpfnOldScr[3] ;
HWND hwndScrol[3], hwndLabel[3], hwndValue[3], hwndRect ;
short color[3], nFocus ;
int PASCAL WinMain (HANDLE hInstance, HANDLE hPrevInstance,
LPSTR lpszCmdLine, int nCmdShow)
{
static char szAppName[] = "Colors1" ;
static char *szColorLabel[] = { "Red", "Green", "Blue" } ;
FARPROC lpfnScrollProc ;
HWND hwnd ;
MSG msg;
short n ;
WNDCLASS wndclass ;
if (hPrevInstance)
return FALSE ;
wndclass.style = CS_HREDRAW | CS_VREDRAW ;
wndclass.lpfnWndProc = WndProc ;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hInstance = hInstance ;
wndclass.hIcon = NULL ;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = CreateSolidBrush (0L) ;
wndclass.lpszMenuName = NULL ;
wndclass.lpszClassName = szAppName ;
RegisterClass (&wndclass) ;
hwnd = CreateWindow (szAppName, "Color Scroll",
WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL) ;
hwndRect = CreateWindow ("static", NULL,
WS_CHILD | WS_VISIBLE | SS_WHITERECT,
0, 0, 0, 0,
hwnd, 9, hInstance, NULL) ;
lpfnScrollProc = MakeProcInstance ((FARPROC) ScrollProc, hInstance) ;
for (n = 0 ; n < 3 ; n++)
{
hwndScrol[n] = CreateWindow ("scrollbar", NULL,
WS_CHILD | WS_VISIBLE | WS_TABSTOP | SBS_VERT,
0, 0, 0, 0,
hwnd, n, hInstance, NULL) ;
hwndLabel[n] = CreateWindow ("static", szColorLabel[n],
WS_CHILD | WS_VISIBLE | SS_CENTER,
0, 0, 0, 0,
hwnd, n + 3, hInstance, NULL) ;
hwndValue[n] = CreateWindow ("static", "0",
WS_CHILD | WS_VISIBLE | SS_CENTER,
0, 0, 0, 0,
hwnd, n + 6, hInstance, NULL) ;
lpfnOldScr[n] = (FARPROC) GetWindowLong (hwndScrol[n], GWL_WNDPROC)
SetWindowLong (hwndScrol[n], GWL_WNDPROC, (LONG) lpfnScrollProc) ;
SetScrollRange (hwndScrol[n], SB_CTL, 0, 255, FALSE) ;
SetScrollPos (hwndScrol[n], SB_CTL, 0, FALSE) ;
}
ShowWindow (hwnd, nCmdShow) ;
UpdateWindow (hwnd);
while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
return msg.wParam ;
}
long FAR PASCAL WndProc (HWND hwnd, WORD message, WORD wParam, LONG lParam)
{
static HBRUSH hBrush[3] ;
char szbuffer[10] ;
HDC hdc ;
POINT point ;
short n, cxClient, cyClient, cyChar ;
TEXTMETRIC tm ;
switch (message)
{
case WM_CREATE :
hBrush[0] = CreateSolidBrush (RGB (255, 0, 0)) ;
hBrush[1] = CreateSolidBrush (RGB (0, 255, 0)) ;
hBrush[2] = CreateSolidBrush (RGB (0, 0, 255)) ;
return 0 ;
case WM_SIZE :
cxClient = LOWORD (lParam) ;
cyClient = HIWORD (lParam) ;
hdc = GetDC (hwnd) ;
GetTextMetrics (hdc, &tm) ;
cyChar = tm.tmHeight ;
ReleaseDC (hwnd, hdc) ;
MoveWindow (hwndRect, 0, 0, cxClient / 2, cyClient, TRUE) ;
for (n = 0 ; n < 3 ; n++)
{
MoveWindow (hwndScrol[n],
(2 * n + 1) * cxClient / 14, 2 * cyChar,
cxClient / 14, cyClient - 4 * cyChar, TRUE) ;
MoveWindow (hwndLabel[n],
(4 * n + 1) * cxClient / 28, cyChar / 2,
cxClient / 7, cyChar, TRUE) ;
MoveWindow (hwndValue[n],
(4 * n + 1) * cxClient / 28, cyClient - 3 * cyChar /
cxClient / 7, cyChar, TRUE) ;
}
SetFocus (hwnd) ;
return 0 ;
case WM_SETFOCUS:
SetFocus (hwndScrol[nFocus]) ;
return 0 ;
case WM_VSCROLL :
n = GetWindowWord (HIWORD (lParam), GWW_ID) ;
switch (wParam)
{
case SB_PAGEDOWN :
color[n] += 15 ; /* fall through */
case SB_LINEDOWN :
color[n] = min (255, color[n] + 1) ;
break ;
case SB_PAGEUP :
color[n] -= 15 ; /* fall through */
case SB_LINEUP :
color[n] = max (0, color[n] - 1) ;
break ;
case SB_TOP:
color[n] = 0 ;
break ;
case SB_BOTTOM :
color[n] = 255 ;
break ;
case SB_THUMBPOSITION :
case SB_THUMBTRACK :
color[n] = LOWORD (lParam) ;
break ;
default :
break ;
}
SetScrollPos (hwndScrol[n], SB_CTL, color[n], TRUE) ;
SetWindowText (hwndValue[n], itoa (color[n], szbuffer, 10)) ;
DeleteObject (GetClassWord (hwnd, GCW_HBRBACKGROUND)) ;
SetClassWord (hwnd, GCW_HBRBACKGROUND,
CreateSolidBrush (RGB (color[0], color[1], color[2]))) ;
InvalidateRect (hwnd, NULL, TRUE) ;
return 0 ;
case WM_CTLCOLOR:
if (HIWORD (lParam) == CTLCOLOR_SCROLLBAR)
{
SetBkColor (wParam, GetSysColor (COLOR_CAPTIONTEXT)) ;
SetTextColor (wParam, GetSysColor (COLOR_WINDOWFRAME)) ;
n = GetWindowWord (LOWORD (lParam), GWW_ID) ;
point.x = point.y = 0 ;
ClientToScreen (hwnd, &point) ;
UnrealizeObject (hBrush[n]) ;
SetBrushOrg (wParam, point.x, point.y) ;
return ((DWORD) hBrush[n]) ;
}
break ;
case WM_DESTROY:
DeleteObject (GetClassWord (hwnd, GCW_HBRBACKGROUND)) ;
for (n = 0 ; n < 3 ; DeleteObject (hBrush [n++])) ;
PostQuitMessage (0) ;
return 0 ;
}
return DefWindowProc (hwnd, message, wParam, lParam) ;
}
long FAR PASCAL ScrollProc (HWND hwnd, WORD message, WORD wParam, LONG lParam
{
short n = GetWindowWord (hwnd, GWW_ID) ;
switch (message)
{
case WM_KEYDOWN:
if (wParam == VK_TAB)
SetFocus (hwndScrol[(n +
(GetKeyState (VK_SHIFT) < 0 ? 2 : 1)) % 3]) ;
break ;
case WM_SETFOCUS:
nFocus = n ;
break ;
}
return CallWindowProc (lpfnOldScr[n], hwnd, message, wParam, lParam) ;
}
COLORS2.C
CD-ROM Disc Path: \SAMPCODE\PROGWIN\CHAP10\COLORS2.C
/*--------------------------------------------------------
COLORS2.C -- Version using Modeless Dialog Box Version
(c) Charles Petzold, 1990
--------------------------------------------------------*/
#include <windows.h>
long FAR PASCAL WndProc (HWND, WORD, WORD, LONG) ;
BOOL FAR PASCAL ColorScrDlg (HWND, WORD, WORD, LONG) ;
HWND hDlgModeless ;
int PASCAL WinMain (HANDLE hInstance, HANDLE hPrevInstance,
LPSTR lpszCmdLine, int nCmdShow)
{
static char szAppName[] = "Colors2" ;
HWND hwnd ;
MSG msg;
WNDCLASS wndclass ;
if (hPrevInstance)
return FALSE ;
wndclass.style = CS_HREDRAW | CS_VREDRAW ;
wndclass.lpfnWndProc = WndProc ;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hInstance = hInstance ;
wndclass.hIcon = NULL ;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = CreateSolidBrush (0L) ;
wndclass.lpszMenuName = NULL ;
wndclass.lpszClassName = szAppName ;
RegisterClass (&wndclass) ;
hwnd = CreateWindow (szAppName, "Color Scroll",
WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL) ;
ShowWindow (hwnd, nCmdShow) ;
UpdateWindow (hwnd);
hDlgModeless = CreateDialog (hInstance, "ColorScrDlg", hwnd,
MakeProcInstance (ColorScrDlg, hInstance)) ;
while (GetMessage (&msg, NULL, 0, 0))
{
if (hDlgModeless == 0 || !IsDialogMessage (hDlgModeless, &msg))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
}
return msg.wParam ;
}
BOOL FAR PASCAL ColorScrDlg (HWND hDlg, WORD message, WORD wParam, LONG lPara
{
static short color [3] ;
HWND hwndParent, hCtrl ;
short nCtrlID, nIndex ;
switch (message)
{
case WM_INITDIALOG:
for (nCtrlID = 10 ; nCtrlID < 13 ; nCtrlID++)
{
hCtrl = GetDlgItem (hDlg, nCtrlID) ;
SetScrollRange (hCtrl, SB_CTL, 0, 255, FALSE) ;
SetScrollPos (hCtrl, SB_CTL, 0, FALSE) ;
}
return TRUE ;
case WM_VSCROLL :
hCtrl = HIWORD (lParam) ;
nCtrlID = GetWindowWord (hCtrl, GWW_ID) ;
nIndex = nCtrlID - 10 ;
hwndParent = GetParent (hDlg) ;
switch (wParam)
{
case SB_PAGEDOWN :
color [nIndex] += 15 ; // fall through
case SB_LINEDOWN :
color [nIndex] = min (255, color [nIndex] + 1) ;
break ;
case SB_PAGEUP :
color [nIndex] -= 15 ; // fall through
case SB_LINEUP :
color [nIndex] = max (0, color [nIndex] - 1) ;
break ;
case SB_TOP:
color [nIndex] = 0 ;
break ;
case SB_BOTTOM :
color [nIndex] = 255 ;
break ;
case SB_THUMBPOSITION :
case SB_THUMBTRACK :
color [nIndex] = LOWORD (lParam) ;
break ;
default :
return FALSE ;
}
SetScrollPos (hCtrl, SB_CTL, color [nIndex], TRUE) ;
SetDlgItemInt (hDlg, nCtrlID + 3, color [nIndex], FALSE) ;
DeleteObject (GetClassWord (hwndParent, GCW_HBRBACKGROUND)) ;
SetClassWord (hwndParent, GCW_HBRBACKGROUND,
CreateSolidBrush (RGB (color [0], color [1], color [2])))
InvalidateRect (hwndParent, NULL, TRUE) ;
return TRUE ;
}
return FALSE ;
}
long FAR PASCAL WndProc (HWND hwnd, WORD message, WORD wParam, LONG lParam)
{
switch (message)
{
case WM_DESTROY:
DeleteObject (GetClassWord (hwnd, GCW_HBRBACKGROUND)) ;
PostQuitMessage (0) ;
return 0 ;
}
return DefWindowProc (hwnd, message, wParam, lParam) ;
}
CONNECT.C
CD-ROM Disc Path: \SAMPCODE\PROGWIN\CHAP04\CONNECT.C
/*--------------------------------------------------
CONNECT.C -- Connect-the-Dots Mouse Demo Program
(c) Charles Petzold, 1990
--------------------------------------------------*/
#include <windows.h>
#define MAXPOINTS 1000
long FAR PASCAL WndProc (HWND, WORD, WORD, LONG) ;
int PASCAL WinMain (HANDLE hInstance, HANDLE hPrevInstance,
LPSTR lpszCmdLine, int nCmdShow)
{
static char szAppName[] = "Connect" ;
HWND hwnd ;
MSG msg ;
WNDCLASS wndclass ;
if (!hPrevInstance)
{
wndclass.style = CS_HREDRAW | CS_VREDRAW ;
wndclass.lpfnWndProc = WndProc ;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hInstance = hInstance ;
wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = GetStockObject (WHITE_BRUSH) ;
wndclass.lpszMenuName = NULL ;
wndclass.lpszClassName = szAppName ;
RegisterClass (&wndclass) ;
}
hwnd = CreateWindow (szAppName, "Connect-the-Points Mouse Demo",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL) ;
ShowWindow (hwnd, nCmdShow) ;
UpdateWindow (hwnd) ;
while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
return msg.wParam ;
}
long FAR PASCAL WndProc (HWND hwnd, WORD message, WORD wParam, LONG lParam)
{
static POINT points[MAXPOINTS] ;
static short nCount ;
HDC hdc ;
PAINTSTRUCT ps ;
short i, j ;
switch (message)
{
case WM_LBUTTONDOWN:
nCount = 0 ;
InvalidateRect (hwnd, NULL, TRUE) ;
return 0 ;
case WM_MOUSEMOVE:
if (wParam & MK_LBUTTON && nCount < 1000)
{
points [nCount++] = MAKEPOINT (lParam) ;
hdc = GetDC (hwnd) ;
SetPixel (hdc, LOWORD (lParam), HIWORD (lParam), 0L) ;
ReleaseDC (hwnd, hdc) ;
}
return 0 ;
case WM_LBUTTONUP:
InvalidateRect (hwnd, NULL, FALSE) ;
return 0 ;
case WM_PAINT:
hdc = BeginPaint (hwnd, &ps) ;
for (i = 0 ; i < nCount - 1 ; i++)
for (j = i ; j < nCount ; j++)
{
MoveTo (hdc, points[i].x, points[i].y) ;
LineTo (hdc, points[j].x, points[j].y) ;
}
EndPaint (hwnd, &ps) ;
return 0 ;
case WM_DESTROY:
PostQuitMessage (0) ;
return 0 ;
}
return DefWindowProc (hwnd, message, wParam, lParam) ;
}
DDEPOP.C
CD-ROM Disc Path: \SAMPCODE\PROGWIN\CHAP17\DDEPOP.C
/*--------------------------------------------
DDEPOP.C -- DDE Server for Population Data
(c) Charles Petzold, 1990
--------------------------------------------*/
#include <windows.h>
#include <dde.h>
#include <string.h>
#include <time.h>
struct
{
char *szState ;
long lPop70 ;
long lPop80 ;
long lPop ;
}
pop [] = {
"AL", 3444354, 3894025, 0, "AK", 302583, 401851, 0,
"AZ", 1775399, 2716598, 0, "AR", 1923322, 2286357, 0,
"CA", 19971069, 23667764, 0, "CO", 2209596, 2889735, 0,
"CT", 3032217, 3107564, 0, "DE", 548104, 594338, 0,
"DC", 756668, 638432, 0, "FL", 6791418, 9746961, 0,
"GA", 4587930, 5462982, 0, "HI", 769913, 964691, 0,
"ID", 713015, 944127, 0, "IL", 11110285, 11427409, 0,
"IN", 5195392, 5490212, 0, "IA", 2825368, 2913808, 0,
"KS", 2249071, 2364236, 0, "KY", 3220711, 3660324, 0,
"LA", 3644637, 4206116, 0, "ME", 993722, 1125043, 0,
"MD", 3923897, 4216933, 0, "MA", 5689170, 5737093, 0,
"MI", 8881826, 9262044, 0, "MN", 3806103, 4075970, 0,
"MS", 2216994, 2520770, 0, "MO", 4677623, 4916762, 0,
"MT", 694409, 786690, 0, "NE", 1485333, 1569825, 0,
"NV", 488738, 800508, 0, "NH", 737681, 920610, 0,
"NJ", 7171112, 7365011, 0, "NM", 1017055, 1303302, 0,
"NY", 18241391, 17558165, 0, "NC", 5084411, 5880415, 0,
"ND", 617792, 652717, 0, "OH", 10657423, 10797603, 0,
"OK", 2559463, 3025487, 0, "OR", 2091533, 2633156, 0,
"PA", 11800766, 11864720, 0, "RI", 949723, 947154, 0,
"SC", 2590713, 3120730, 0, "SD", 666257, 690768, 0,
"TN", 3926018, 4591023, 0, "TX", 11198655, 14225513, 0,
"UT", 1059273, 1461037, 0, "VT", 444732, 511456, 0,
"VA", 4651448, 5346797, 0, "WA", 3413244, 4132353, 0,
"WV", 1744237, 1950186, 0, "WI", 4417821, 4705642, 0,
"WY", 332416, 469557, 0, "US", 203302031, 226542580, 0
} ;
#define NUM_STATES (sizeof (pop) / sizeof (pop [0]))
typedef struct
{
unsigned int fAdvise:1 ;
unsigned int fDeferUpd:1 ;
unsigned int fAckReq:1 ;
unsigned int dummy:13 ;
long lPopPrev ;
}
POPADVISE ;
#define ID_TIMER 1
#define DDE_TIMEOUT 3000
long FAR PASCAL WndProc (HWND, WORD, WORD, LONG) ;
long FAR PASCAL ServerProc (HWND, WORD, WORD, LONG) ;
BOOL FAR PASCAL TimerEnumProc (HWND, LONG) ;
BOOL FAR PASCAL CloseEnumProc (HWND, LONG) ;
BOOL PostDataMessage (HWND, HWND, int, BOOL, BOOL, BOOL) ;
char szAppName [] = "DdePop" ;
char szServerClass [] = "DdePop.Server" ;
HANDLE hInst ;
int PASCAL WinMain (HANDLE hInstance, HANDLE hPrevInstance,
LPSTR lpszCmdLine, int nCmdShow)
{
HWND hwnd ;
MSG msg ;
WNDCLASS wndclass ;
if (hPrevInstance)
return FALSE ;
hInst = hInstance ;
// Register window class
wndclass.style = 0 ;
wndclass.lpfnWndProc = WndProc ;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hInstance = hInstance ;
wndclass.hIcon = LoadIcon (hInstance, szAppName) ;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = GetStockObject (WHITE_BRUSH) ;
wndclass.lpszMenuName = NULL ;
wndclass.lpszClassName = szAppName ;
RegisterClass (&wndclass) ;
// Register window class for DDE Server
wndclass.style = 0 ;
wndclass.lpfnWndProc = ServerProc ;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 2 * sizeof (WORD) ;
wndclass.hInstance = hInstance ;
wndclass.hIcon = NULL ;
wndclass.hCursor = NULL ;
wndclass.hbrBackground = NULL ;
wndclass.lpszMenuName = NULL ;
wndclass.lpszClassName = szServerClass ;
RegisterClass (&wndclass) ;
hwnd = CreateWindow (szAppName, "DDE Population Server",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL) ;
SendMessage (hwnd, WM_TIMER, 0, 0L) ; // initialize 'pop' structure
if (!SetTimer (hwnd, ID_TIMER, 5000, NULL))
{
MessageBox (hwnd, "Too many clocks or timers!", szAppName,
MB_ICONEXCLAMATION | MB_OK) ;
return FALSE ;
}
ShowWindow (hwnd, SW_SHOWMINNOACTIVE) ;
UpdateWindow (hwnd) ;
while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
KillTimer (hwnd, ID_TIMER) ;
return msg.wParam ;
}
long FAR PASCAL WndProc (HWND hwnd, WORD message, WORD wParam, LONG lParam)
{
static FARPROC lpTimerEnumProc, lpCloseEnumProc ;
static char szTopic [] = "US_Population" ;
ATOM aApp, aTop ;
HWND hwndClient, hwndServer ;
int i ;
long double ldSecsInDecade, ldSecSince1970 ;
time_t lSecSince1970 ;
switch (message)
{
case WM_CREATE:
lpTimerEnumProc = MakeProcInstance (TimerEnumProc, hInst) ;
lpCloseEnumProc = MakeProcInstance (CloseEnumProc, hInst) ;
return 0 ;
case WM_DDE_INITIATE:
// wParam -- sending window handle
// LOWORD (lParam) -- application atom
// HIWORD (lParam) -- topic atom
hwndClient = wParam ;
aApp = GlobalAddAtom (szAppName) ;
aTop = GlobalAddAtom (szTopic) ;
// Check for matching atoms, create window, and acknowled
if ((LOWORD (lParam) == NULL || LOWORD (lParam) == aApp) &&
(HIWORD (lParam) == NULL || HIWORD (lParam) == aTop))
{
hwndServer = CreateWindow (szServerClass, NULL,
WS_CHILD, 0, 0, 0, 0,
hwnd, NULL, hInst, NULL) ;
SetWindowWord (hwndServer, 0, hwndClient) ;
SendMessage (wParam, WM_DDE_ACK, hwndServer,
MAKELONG (aApp, aTop)) ;
}
// Otherwise, delete the atoms just created
else
{
GlobalDeleteAtom (aApp) ;
GlobalDeleteAtom (aTop) ;
}
return 0 ;
case WM_TIMER:
case WM_TIMECHANGE:
time (&lSecSince1970) ;
// Calculate new current populations
ldSecSince1970 = (long double) lSecSince1970 ;
ldSecsInDecade = (long double) 3652 * 24 * 60 * 60 ;
for (i = 0 ; i < NUM_STATES ; i++)
{
pop[i].lPop = (long)
(((ldSecsInDecade - ldSecSince1970) * pop[i].lPop70
ldSecSince1970 * pop[i].lPop80) / ldSecsInDecade
+ .5) ;
}
// Notify all child windows
EnumChildWindows (hwnd, lpTimerEnumProc, 0L) ;
return 0 ;
case WM_QUERYOPEN:
return 0 ;
case WM_CLOSE:
// Notify all child windows
EnumChildWindows (hwnd, lpCloseEnumProc, 0L) ;
break ; // for default processing
case WM_DESTROY:
PostQuitMessage (0) ;
return 0 ;
}
return DefWindowProc (hwnd, message, wParam, lParam) ;
}
long FAR PASCAL ServerProc (HWND hwnd, WORD message, WORD wParam, LONG lParam
{
ATOM aItem ;
char szItem [10], szPopulation [10] ;
DDEACK DdeAck ;
DDEADVISE Advise ;
DDEADVISE FAR *lpDdeAdvise ;
DDEDATA FAR *lpDdeData ;
DWORD dwTime ;
GLOBALHANDLE hPopAdvise, hDdeData, hDdeAdvise, hCommands, hDdePoke ;
int i ;
HWND hwndClient ;
MSG msg ;
POPADVISE FAR *lpPopAdvise ;
WORD cfFormat, wStatus ;
switch (message)
{
case WM_CREATE:
// Allocate memory for POPADVISE structures
hPopAdvise = GlobalAlloc (GHND, NUM_STATES * sizeof (POPADVISE
if (hPopAdvise == NULL)
DestroyWindow (hwnd) ;
else
SetWindowWord (hwnd, 2, hPopAdvise) ;
return 0 ;
case WM_DDE_REQUEST:
// wParam -- sending window handle
// LOWORD (lParam) -- data format
// HIWORD (lParam) -- item atom
hwndClient = wParam ;
cfFormat = LOWORD (lParam) ;
aItem = HIWORD (lParam) ;
// Check for matching format and data item
if (cfFormat == CF_TEXT)
{
GlobalGetAtomName (aItem, szItem, sizeof (szItem)) ;
for (i = 0 ; i < NUM_STATES ; i++)
if (strcmp (szItem, pop[i].szState) == 0)
break ;
if (i < NUM_STATES)
{
GlobalDeleteAtom (aItem) ;
PostDataMessage (hwnd, hwndClient, i,
FALSE, FALSE, TRUE) ;
return 0 ;
}
}
// Negative acknowledge if no match
DdeAck.bAppReturnCode = 0 ;
DdeAck.reserved = 0 ;
DdeAck.fBusy = FALSE ;
DdeAck.fAck = FALSE ;
wStatus = * (WORD *) & DdeAck ;
if (!PostMessage (hwndClient, WM_DDE_ACK, hwnd,
MAKELONG (wStatus, aItem)))
{
GlobalDeleteAtom (aItem) ;
}
return 0 ;
case WM_DDE_ADVISE:
// wParam -- sending window handle
// LOWORD (lParam) -- DDEADVISE memory handle
// HIWORD (lParam) -- item atom
hwndClient = wParam ;
hDdeAdvise = LOWORD (lParam) ;
aItem = HIWORD (lParam) ;
lpDdeAdvise = (DDEADVISE FAR *) GlobalLock (hDdeAdvise) ;
// Check for matching format and data item
if (lpDdeAdvise->cfFormat == CF_TEXT)
{
GlobalGetAtomName (aItem, szItem, sizeof (szItem)) ;
for (i = 0 ; i < NUM_STATES ; i++)
if (strcmp (szItem, pop[i].szState) == 0)
break ;
// Fill in the POPADVISE structure and acknowledge
if (i < NUM_STATES)
{
hPopAdvise = GetWindowWord (hwnd, 2) ;
lpPopAdvise = (POPADVISE FAR *)
GlobalLock (hPopAdvise) ;
lpPopAdvise[i].fAdvise = TRUE ;
lpPopAdvise[i].fDeferUpd = lpDdeAdvise->fDeferUpd ;
lpPopAdvise[i].fAckReq = lpDdeAdvise->fAckReq ;
lpPopAdvise[i].lPopPrev = pop[i].lPop ;
GlobalUnlock (hDdeAdvise) ;
GlobalFree (hDdeAdvise) ;
DdeAck.bAppReturnCode = 0 ;
DdeAck.reserved = 0 ;
DdeAck.fBusy = FALSE ;
DdeAck.fAck = TRUE ;
wStatus = * (WORD *) & DdeAck ;
if (!PostMessage (hwndClient, WM_DDE_ACK, hwnd,
MAKELONG (wStatus, aItem)))
{
GlobalDeleteAtom (aItem) ;
}
else
{
PostDataMessage (hwnd, hwndClient, i,
lpPopAdvise[i].fDeferUpd,
lpPopAdvise[i].fAckReq,
FALSE) ;
}
GlobalUnlock (hPopAdvise) ;
return 0 ;
}
}
// Otherwise post a negative WM_DDE_ACK
GlobalUnlock (hDdeAdvise) ;
DdeAck.bAppReturnCode = 0 ;
DdeAck.reserved = 0 ;
DdeAck.fBusy = FALSE ;
DdeAck.fAck = FALSE ;
wStatus = * (WORD *) & DdeAck ;
if (!PostMessage (hwndClient, WM_DDE_ACK, hwnd,
MAKELONG (wStatus, aItem)))
{
GlobalFree (hDdeAdvise) ;
GlobalDeleteAtom (aItem) ;
}
return 0 ;
case WM_DDE_UNADVISE:
// wParam -- sending window handle
// LOWORD (lParam) -- data format
// HIWORD (lParam) -- item atom
hwndClient = wParam ;
cfFormat = LOWORD (lParam) ;
aItem = HIWORD (lParam) ;
DdeAck.bAppReturnCode = 0 ;
DdeAck.reserved = 0 ;
DdeAck.fBusy = FALSE ;
DdeAck.fAck = TRUE ;
hPopAdvise = GetWindowWord (hwnd, 2) ;
lpPopAdvise = (POPADVISE FAR *) GlobalLock (hPopAdvise) ;
// Check for matching format and data item
if (cfFormat == CF_TEXT || cfFormat == 0)
{
if (aItem == NULL)
for (i = 0 ; i < NUM_STATES ; i++)
lpPopAdvise[i].fAdvise = FALSE ;
else
{
GlobalGetAtomName (aItem, szItem, sizeof (szItem)) ;
for (i = 0 ; i < NUM_STATES ; i++)
if (strcmp (szItem, pop[i].szState) == 0)
break ;
if (i < NUM_STATES)
lpPopAdvise[i].fAdvise = FALSE ;
else
DdeAck.fAck = FALSE ;
}
}
else
DdeAck.fAck = FALSE ;
// Acknowledge either positively or negatively
wStatus = * (WORD *) & DdeAck ;
if (!PostMessage (hwndClient, WM_DDE_ACK, hwnd,
MAKELONG (wStatus, aItem)))
{
if (aItem != NULL)
GlobalDeleteAtom (aItem) ;
}
GlobalUnlock (hPopAdvise) ;
return 0 ;
case WM_DDE_EXECUTE:
// Post negative acknowledge
hwndClient = wParam ;
hCommands = HIWORD (lParam) ;
DdeAck.bAppReturnCode = 0 ;
DdeAck.reserved = 0 ;
DdeAck.fBusy = FALSE ;
DdeAck.fAck = FALSE ;
wStatus = * (WORD *) & DdeAck ;
if (!PostMessage (hwndClient, WM_DDE_ACK, hwnd,
MAKELONG (wStatus, hCommands)))
{
GlobalFree (hCommands) ;
}
return 0 ;
case WM_DDE_POKE:
// Post negative acknowledge
hwndClient = wParam ;
hDdePoke = LOWORD (lParam) ;
aItem = HIWORD (lParam) ;
DdeAck.bAppReturnCode = 0 ;
DdeAck.reserved = 0 ;
DdeAck.fBusy = FALSE ;
DdeAck.fAck = FALSE ;
wStatus = * (WORD *) & DdeAck ;
if (!PostMessage (hwndClient, WM_DDE_ACK, hwnd,
MAKELONG (wStatus, aItem)))
{
GlobalFree (hDdePoke) ;
GlobalDeleteAtom (aItem) ;
}
return 0 ;
case WM_DDE_TERMINATE:
// Respond with another WM_DDE_TERMINATE message
hwndClient = wParam ;
PostMessage (hwndClient, WM_DDE_TERMINATE, hwnd, 0L) ;
DestroyWindow (hwnd) ;
return 0 ;
case WM_TIMER:
// Post WM_DDE_DATA messages for changed populations
hwndClient = GetWindowWord (hwnd, 0) ;
hPopAdvise = GetWindowWord (hwnd, 2) ;
lpPopAdvise = (POPADVISE FAR *) GlobalLock (hPopAdvise) ;
for (i = 0 ; i < NUM_STATES ; i++)
if (lpPopAdvise[i].fAdvise)
if (lpPopAdvise[i].lPopPrev != pop[i].lPop)
{
if (!PostDataMessage (hwnd, hwndClient, i,
lpPopAdvise[i].fDeferUpd,
lpPopAdvise[i].fAckReq,
FALSE))
break ;
lpPopAdvise[i].lPopPrev = pop[i].lPop ;
}
GlobalUnlock (hPopAdvise) ;
return 0 ;
case WM_CLOSE:
// Post a WM_DDE_TERMINATE message to the client
hwndClient = GetWindowWord (hwnd, 0) ;
PostMessage (hwndClient, WM_DDE_TERMINATE, hwnd, 0L) ;
dwTime = GetCurrentTime () ;
while (GetCurrentTime () - dwTime < DDE_TIMEOUT)
if (PeekMessage (&msg, hwnd, WM_DDE_TERMINATE,
WM_DDE_TERMINATE, PM_REMOVE))
break ;
DestroyWindow (hwnd) ;
return 0 ;
case WM_DESTROY:
hPopAdvise = GetWindowWord (hwnd, 2) ;
GlobalFree (hPopAdvise) ;
return 0 ;
}
return DefWindowProc (hwnd, message, wParam, lParam) ;
}
BOOL FAR PASCAL TimerEnumProc (HWND hwnd, LONG lParam)
{
SendMessage (hwnd, WM_TIMER, 0, 0L) ;
return TRUE ;
}
BOOL FAR PASCAL CloseEnumProc (HWND hwnd, LONG lParam)
{
SendMessage (hwnd, WM_CLOSE, 0, 0L) ;
return TRUE ;
}
BOOL PostDataMessage (HWND hwndServer, HWND hwndClient, int iState,
BOOL fDeferUpd, BOOL fAckReq, BOOL fResponse)
{
ATOM aItem ;
char szPopulation [10] ;
DDEACK DdeAck ;
DDEDATA FAR *lpDdeData ;
DWORD dwTime ;
GLOBALHANDLE hDdeData ;
MSG msg ;
aItem = GlobalAddAtom (pop[iState].szState) ;
// Allocate a DDEDATA structure if not defered update
if (fDeferUpd)
{
hDdeData = NULL ;
}
else
{
wsprintf (szPopulation, "%ld\r\n", pop[iState].lPop) ;
hDdeData = GlobalAlloc (GHND | GMEM_DDESHARE,
sizeof (DDEDATA) + strlen (szPopulation)) ;
lpDdeData = (DDEDATA FAR *) GlobalLock (hDdeData) ;
lpDdeData->fResponse = fResponse ;
lpDdeData->fRelease = TRUE ;
lpDdeData->fAckReq = fAckReq ;
lpDdeData->cfFormat = CF_TEXT ;
lstrcpy ((LPSTR) lpDdeData->Value, szPopulation) ;
GlobalUnlock (hDdeData) ;
}
// Post the WM_DDE_DATA message
if (!PostMessage (hwndClient, WM_DDE_DATA, hwndServer,
MAKELONG (hDdeData, aItem)))
{
if (hDdeData != NULL)
GlobalFree (hDdeData) ;
GlobalDeleteAtom (aItem) ;
return FALSE ;
}
// Wait for the acknowledge message if it's requested
if (fAckReq)
{
DdeAck.fAck = FALSE ;
dwTime = GetCurrentTime () ;
while (GetCurrentTime () - dwTime < DDE_TIMEOUT)
{
if (PeekMessage (&msg, hwndServer, WM_DDE_ACK, WM_DDE_ACK,
PM_REMOVE))
{
DdeAck = * (DDEACK *) & LOWORD (msg.lParam) ;
aItem = HIWORD (msg.lParam) ;
GlobalDeleteAtom (aItem) ;
break ;
}
}
if (DdeAck.fAck == FALSE)
{
if (hDdeData != NULL)
GlobalFree (hDdeData) ;
return FALSE ;
}
}
return TRUE ;
}
DEVCAPS.C
CD-ROM Disc Path: \SAMPCODE\PROGWIN\CHAP15\DEVCAPS.C
/*---------------------------------------------------------
DEVCAPS.C -- Display routines for DEVCAPS1 and DEVCAPS2
(c) Charles Petzold, 1990
---------------------------------------------------------*/
#include <windows.h>
#include <string.h>
#include <stdio.h>
typedef struct
{
short nMask ;
char *szMask ;
char *szDesc ;
}
BITS ;
void DoBasicInfo (HDC hdc, HDC hdcInfo, short cxChar, short cyChar)
{
static struct
{
short nIndex ;
char *szDesc ;
}
info [] =
{
HORZSIZE, "HORZSIZE Width in millimeters:",
VERTSIZE, "VERTSIZE Height in millimeters:",
HORZRES, "HORZRES Width in pixels:",
VERTRES, "VERTRES Height in raster lines:",
BITSPIXEL, "BITSPIXEL Color bits per pixel:",
PLANES, "PLANES Number of color planes:",
NUMBRUSHES, "NUMBRUSHES Number of device brushes:",
NUMPENS, "NUMPENS Number of device pens:",
NUMMARKERS, "NUMMARKERS Number of device markers:",
NUMFONTS, "NUMFONTS Number of device fonts:",
NUMCOLORS, "NUMCOLORS Number of device colors:",
PDEVICESIZE, "PDEVICESIZE Size of device structure:",
ASPECTX, "ASPECTX Relative width of pixel:",
ASPECTY, "ASPECTY Relative height of pixel:",
ASPECTXY, "ASPECTXY Relative diagonal of pixel:",
LOGPIXELSX, "LOGPIXELSX Horizontal dots per inch:",
LOGPIXELSY, "LOGPIXELSY Vertical dots per inch:",
SIZEPALETTE, "SIZEPALETTE Number of palette entries:",
NUMRESERVED, "NUMRESERVED Reserved palette entries:",
COLORRES, "COLORRES Actual color resolution:"
} ;
char szBuffer [80] ;
short i, nLine ;
for (i = 0 ; i < sizeof info / sizeof info [0] ; i++)
TextOut (hdc, cxChar, (i + 1) * cyChar, szBuffer,
sprintf (szBuffer, "%-40s%8d", info[i].szDesc,
GetDeviceCaps (hdcInfo, info[i].nIndex))) ;
}
void DoOtherInfo (HDC hdc, HDC hdcInfo, short cxChar, short cyChar)
{
static BITS clip [] =
{
CP_RECTANGLE, "CP_RECTANGLE", "Can Clip To Rectangle:"
} ;
static BITS raster [] =
{
RC_BITBLT, "RC_BITBLT", "Capable of simple BitBlt:",
RC_BANDING, "RC_BANDING", "Requires banding support:",
RC_SCALING, "RC_SCALING", "Requires scaling support:",
RC_BITMAP64, "RC_BITMAP64", "Supports bitmaps >64K:",
RC_GDI20_OUTPUT, "RC_GDI20_OUTPUT", "Has 2.0 output calls:",
RC_DI_BITMAP, "RC_DI_BITMAP", "Supports DIB to memory:",
RC_PALETTE, "RC_PALETTE", "Supports a palette:",
RC_DIBTODEV, "RC_DIBTODEV", "Supports bitmap conversion:",
RC_BIGFONT, "RC_BIGFONT", "Supports fonts >64K:",
RC_STRETCHBLT, "RC_STRETCHBLT", "Supports StretchBlt:",
RC_FLOODFILL, "RC_FLOODFILL", "Supports FloodFill:"
} ;
static char *szTech [] = { "DT_PLOTTER (Vector plotter)",
"DT_RASDISPLAY (Raster display)",
"DT_RASPRINTER (Raster printer)",
"DT_RASCAMERA (Raster camera)",
"DT_CHARSTREAM (Character-stream, PLP)",
"DT_METAFILE (Metafile, VDM)",
"DT_DISPFILE (Display-file)" } ;
char szBuffer [80] ;
short i ;
TextOut (hdc, cxChar, cyChar, szBuffer,
sprintf (szBuffer, "%-24s%04XH",
"DRIVERVERSION:", GetDeviceCaps (hdcInfo, DRIVERVERSION))) ;
TextOut (hdc, cxChar, 2 * cyChar, szBuffer,
sprintf (szBuffer, "%-24s%-40s",
"TECHNOLOGY:", szTech [GetDeviceCaps (hdcInfo, TECHNOLOGY)]))
TextOut (hdc, cxChar, 4 * cyChar, szBuffer,
sprintf (szBuffer, "CLIPCAPS (Clipping capabilities)")) ;
for (i = 0 ; i < sizeof clip / sizeof clip [0] ; i++)
TextOut (hdc, 9 * cxChar, (i + 6) * cyChar, szBuffer,
sprintf (szBuffer, "%-16s%-28s %3s",
clip[i].szMask, clip[i].szDesc,
GetDeviceCaps (hdcInfo, CLIPCAPS) & clip[i].nMask ?
"Yes" : "No")) ;
TextOut (hdc, cxChar, 8 * cyChar, szBuffer,
sprintf (szBuffer, "RASTERCAPS (Raster capabilities)")) ;
for (i = 0 ; i < sizeof raster / sizeof raster [0] ; i++)
TextOut (hdc, 9 * cxChar, (i + 10) * cyChar, szBuffer,
sprintf (szBuffer, "%-16s%-28s %3s",
raster[i].szMask, raster[i].szDesc,
GetDeviceCaps (hdcInfo, RASTERCAPS) & raster[i].nMask ?
"Yes" : "No")) ;
}
void DoBitCodedCaps (HDC hdc, HDC hdcInfo, short cxChar, short cyChar,
short nType)
{
static BITS curves [] =
{
CC_CIRCLES, "CC_CIRCLES", "circles:",
CC_PIE, "CC_PIE", "pie wedges:",
CC_CHORD, "CC_CHORD", "chord arcs:",
CC_ELLIPSES, "CC_ELLIPSES", "ellipses:",
CC_WIDE, "CC_WIDE", "wide borders:",
CC_STYLED, "CC_STYLED", "styled borders:",
CC_WIDESTYLED, "CC_WIDESTYLED", "wide and styled borders:",
CC_INTERIORS, "CC_INTERIORS", "interiors:"
} ;
static BITS lines [] =
{
LC_POLYLINE, "LC_POLYLINE", "polyline:",
LC_MARKER, "LC_MARKER", "markers:",
LC_POLYMARKER, "LC_POLYMARKER", "polymarkers",
LC_WIDE, "LC_WIDE", "wide lines:",
LC_STYLED, "LC_STYLED", "styled lines:",
LC_WIDESTYLED, "LC_WIDESTYLED", "wide and styled lines:",
LC_INTERIORS, "LC_INTERIORS", "interiors:"
} ;
static BITS poly [] =
{
PC_POLYGON, "PC_POLYGON", "alternate fill polygon:",
PC_RECTANGLE, "PC_RECTANGLE", "rectangle:",
PC_TRAPEZOID, "PC_TRAPEZOID", "winding number fill polygon:",
PC_SCANLINE, "PC_SCANLINE", "scanlines:",
PC_WIDE, "PC_WIDE", "wide borders:",
PC_STYLED, "PC_STYLED", "styled borders:",
PC_WIDESTYLED, "PC_WIDESTYLED", "wide and styled borders:",
PC_INTERIORS, "PC_INTERIORS", "interiors:"
} ;
static BITS text [] =
{
TC_OP_CHARACTER, "TC_OP_CHARACTER", "character output precision:",
TC_OP_STROKE, "TC_OP_STROKE", "stroke output precision:",
TC_CP_STROKE, "TC_CP_STROKE", "stroke clip precision:",
TC_CR_90, "TC_CP_90", "90 degree character rotation:"
TC_CR_ANY, "TC_CR_ANY", "any character rotation:",
TC_SF_X_YINDEP, "TC_SF_X_YINDEP", "scaling independent of X and Y:
TC_SA_DOUBLE, "TC_SA_DOUBLE", "doubled character for scaling:"
TC_SA_INTEGER, "TC_SA_INTEGER", "integer multiples for scaling:"
TC_SA_CONTIN, "TC_SA_CONTIN", "any multiples for exact scaling:
TC_EA_DOUBLE, "TC_EA_DOUBLE", "double weight characters:",
TC_IA_ABLE, "TC_IA_ABLE", "italicizing:",
TC_UA_ABLE, "TC_UA_ABLE", "underlining:",
TC_SO_ABLE, "TC_SO_ABLE", "strikeouts:",
TC_RA_ABLE, "TC_RA_ABLE", "raster fonts:",
TC_VA_ABLE, "TC_VA_ABLE", "vector fonts:"
} ;
static struct
{
short nIndex ;
char *szTitle ;
BITS (*pbits) [] ;
short nSize ;
}
bitinfo [] =
{
CURVECAPS, "CURVCAPS (Curve Capabilities)",
(BITS (*)[]) curves, sizeof curves / sizeof curves [0],
LINECAPS, "LINECAPS (Line Capabilities)",
(BITS (*)[]) lines, sizeof lines / sizeof lines [0],
POLYGONALCAPS, "POLYGONALCAPS (Polygonal Capabilities)",
(BITS (*)[]) poly, sizeof poly / sizeof poly [0],
TEXTCAPS, "TEXTCAPS (Text Capabilities)",
(BITS (*)[]) text, sizeof text / sizeof text [0]
} ;
static char szBuffer [80] ;
BITS (*pbits) [] = bitinfo [nType].pbits ;
short nDevCaps = GetDeviceCaps (hdcInfo, bitinfo [nType].nIndex) ;
short i ;
TextOut (hdc, cxChar, cyChar, bitinfo [nType].szTitle,
strlen (bitinfo [nType].szTitle)) ;
for (i = 0 ; i < bitinfo [nType].nSize ; i++)
TextOut (hdc, cxChar, (i + 3) * cyChar, szBuffer,
sprintf (szBuffer, "%-16s %s %-32s %3s",
(*pbits)[i].szMask, "Can do", (*pbits)[i].szDesc,
nDevCaps & (*pbits)[i].nMask ? "Yes" : "No")) ;
}
DEVCAPS.C
CD-ROM Disc Path: \SAMPCODE\PROGWIN\CHAP11\DEVCAPS.C
/*---------------------------------------------------------
DEVCAPS.C -- Display routines for DEVCAPS1 and DEVCAPS2
(c) Charles Petzold, 1990
---------------------------------------------------------*/
#include <windows.h>
#include <string.h>
#include <stdio.h>
typedef struct
{
short nMask ;
char *szMask ;
char *szDesc ;
}
BITS ;
void DoBasicInfo (HDC hdc, HDC hdcInfo, short cxChar, short cyChar)
{
static struct
{
short nIndex ;
char *szDesc ;
}
info [] =
{
HORZSIZE, "HORZSIZE Width in millimeters:",
VERTSIZE, "VERTSIZE Height in millimeters:",
HORZRES, "HORZRES Width in pixels:",
VERTRES, "VERTRES Height in raster lines:",
BITSPIXEL, "BITSPIXEL Color bits per pixel:",
PLANES, "PLANES Number of color planes:",
NUMBRUSHES, "NUMBRUSHES Number of device brushes:",
NUMPENS, "NUMPENS Number of device pens:",
NUMMARKERS, "NUMMARKERS Number of device markers:",
NUMFONTS, "NUMFONTS Number of device fonts:",
NUMCOLORS, "NUMCOLORS Number of device colors:",
PDEVICESIZE, "PDEVICESIZE Size of device structure:",
ASPECTX, "ASPECTX Relative width of pixel:",
ASPECTY, "ASPECTY Relative height of pixel:",
ASPECTXY, "ASPECTXY Relative diagonal of pixel:",
LOGPIXELSX, "LOGPIXELSX Horizontal dots per inch:",
LOGPIXELSY, "LOGPIXELSY Vertical dots per inch:",
SIZEPALETTE, "SIZEPALETTE Number of palette entries:",
NUMRESERVED, "NUMRESERVED Reserved palette entries:",
COLORRES, "COLORRES Actual color resolution:"
} ;
char szBuffer [80] ;
short i, nLine ;
for (i = 0 ; i < sizeof info / sizeof info [0] ; i++)
TextOut (hdc, cxChar, (i + 1) * cyChar, szBuffer,
sprintf (szBuffer, "%-40s%8d", info[i].szDesc,
GetDeviceCaps (hdcInfo, info[i].nIndex))) ;
}
void DoOtherInfo (HDC hdc, HDC hdcInfo, short cxChar, short cyChar)
{
static BITS clip [] =
{
CP_RECTANGLE, "CP_RECTANGLE", "Can Clip To Rectangle:"
} ;
static BITS raster [] =
{
RC_BITBLT, "RC_BITBLT", "Capable of simple BitBlt:",
RC_BANDING, "RC_BANDING", "Requires banding support:",
RC_SCALING, "RC_SCALING", "Requires scaling support:",
RC_BITMAP64, "RC_BITMAP64", "Supports bitmaps >64K:",
RC_GDI20_OUTPUT, "RC_GDI20_OUTPUT", "Has 2.0 output calls:",
RC_DI_BITMAP, "RC_DI_BITMAP", "Supports DIB to memory:",
RC_PALETTE, "RC_PALETTE", "Supports a palette:",
RC_DIBTODEV, "RC_DIBTODEV", "Supports bitmap conversion:",
RC_BIGFONT, "RC_BIGFONT", "Supports fonts >64K:",
RC_STRETCHBLT, "RC_STRETCHBLT", "Supports StretchBlt:",
RC_FLOODFILL, "RC_FLOODFILL", "Supports FloodFill:"
} ;
static char *szTech [] = { "DT_PLOTTER (Vector plotter)",
"DT_RASDISPLAY (Raster display)",
"DT_RASPRINTER (Raster printer)",
"DT_RASCAMERA (Raster camera)",
"DT_CHARSTREAM (Character-stream, PLP)",
"DT_METAFILE (Metafile, VDM)",
"DT_DISPFILE (Display-file)" } ;
char szBuffer [80] ;
short i ;
TextOut (hdc, cxChar, cyChar, szBuffer,
sprintf (szBuffer, "%-24s%04XH",
"DRIVERVERSION:", GetDeviceCaps (hdcInfo, DRIVERVERSION))) ;
TextOut (hdc, cxChar, 2 * cyChar, szBuffer,
sprintf (szBuffer, "%-24s%-40s",
"TECHNOLOGY:", szTech [GetDeviceCaps (hdcInfo, TECHNOLOGY)]))
TextOut (hdc, cxChar, 4 * cyChar, szBuffer,
sprintf (szBuffer, "CLIPCAPS (Clipping capabilities)")) ;
for (i = 0 ; i < sizeof clip / sizeof clip [0] ; i++)
TextOut (hdc, 9 * cxChar, (i + 6) * cyChar, szBuffer,
sprintf (szBuffer, "%-16s%-28s %3s",
clip[i].szMask, clip[i].szDesc,
GetDeviceCaps (hdcInfo, CLIPCAPS) & clip[i].nMask ?
"Yes" : "No")) ;
TextOut (hdc, cxChar, 8 * cyChar, szBuffer,
sprintf (szBuffer, "RASTERCAPS (Raster capabilities)")) ;
for (i = 0 ; i < sizeof raster / sizeof raster [0] ; i++)
TextOut (hdc, 9 * cxChar, (i + 10) * cyChar, szBuffer,
sprintf (szBuffer, "%-16s%-28s %3s",
raster[i].szMask, raster[i].szDesc,
GetDeviceCaps (hdcInfo, RASTERCAPS) & raster[i].nMask ?
"Yes" : "No")) ;
}
void DoBitCodedCaps (HDC hdc, HDC hdcInfo, short cxChar, short cyChar,
short nType)
{
static BITS curves [] =
{
CC_CIRCLES, "CC_CIRCLES", "circles:",
CC_PIE, "CC_PIE", "pie wedges:",
CC_CHORD, "CC_CHORD", "chord arcs:",
CC_ELLIPSES, "CC_ELLIPSES", "ellipses:",
CC_WIDE, "CC_WIDE", "wide borders:",
CC_STYLED, "CC_STYLED", "styled borders:",
CC_WIDESTYLED, "CC_WIDESTYLED", "wide and styled borders:",
CC_INTERIORS, "CC_INTERIORS", "interiors:"
} ;
static BITS lines [] =
{
LC_POLYLINE, "LC_POLYLINE", "polyline:",
LC_MARKER, "LC_MARKER", "markers:",
LC_POLYMARKER, "LC_POLYMARKER", "polymarkers",
LC_WIDE, "LC_WIDE", "wide lines:",
LC_STYLED, "LC_STYLED", "styled lines:",
LC_WIDESTYLED, "LC_WIDESTYLED", "wide and styled lines:",
LC_INTERIORS, "LC_INTERIORS", "interiors:"
} ;
static BITS poly [] =
{
PC_POLYGON, "PC_POLYGON", "alternate fill polygon:",
PC_RECTANGLE, "PC_RECTANGLE", "rectangle:",
PC_TRAPEZOID, "PC_TRAPEZOID", "winding number fill polygon:",
PC_SCANLINE, "PC_SCANLINE", "scanlines:",
PC_WIDE, "PC_WIDE", "wide borders:",
PC_STYLED, "PC_STYLED", "styled borders:",
PC_WIDESTYLED, "PC_WIDESTYLED", "wide and styled borders:",
PC_INTERIORS, "PC_INTERIORS", "interiors:"
} ;
static BITS text [] =
{
TC_OP_CHARACTER, "TC_OP_CHARACTER", "character output precision:",
TC_OP_STROKE, "TC_OP_STROKE", "stroke output precision:",
TC_CP_STROKE, "TC_CP_STROKE", "stroke clip precision:",
TC_CR_90, "TC_CP_90", "90 degree character rotation:"
TC_CR_ANY, "TC_CR_ANY", "any character rotation:",
TC_SF_X_YINDEP, "TC_SF_X_YINDEP", "scaling independent of X and Y:
TC_SA_DOUBLE, "TC_SA_DOUBLE", "doubled character for scaling:"
TC_SA_INTEGER, "TC_SA_INTEGER", "integer multiples for scaling:"
TC_SA_CONTIN, "TC_SA_CONTIN", "any multiples for exact scaling:
TC_EA_DOUBLE, "TC_EA_DOUBLE", "double weight characters:",
TC_IA_ABLE, "TC_IA_ABLE", "italicizing:",
TC_UA_ABLE, "TC_UA_ABLE", "underlining:",
TC_SO_ABLE, "TC_SO_ABLE", "strikeouts:",
TC_RA_ABLE, "TC_RA_ABLE", "raster fonts:",
TC_VA_ABLE, "TC_VA_ABLE", "vector fonts:"
} ;
static struct
{
short nIndex ;
char *szTitle ;
BITS (*pbits) [] ;
short nSize ;
}
bitinfo [] =
{
CURVECAPS, "CURVCAPS (Curve Capabilities)",
(BITS (*)[]) curves, sizeof curves / sizeof curves [0],
LINECAPS, "LINECAPS (Line Capabilities)",
(BITS (*)[]) lines, sizeof lines / sizeof lines [0],
POLYGONALCAPS, "POLYGONALCAPS (Polygonal Capabilities)",
(BITS (*)[]) poly, sizeof poly / sizeof poly [0],
TEXTCAPS, "TEXTCAPS (Text Capabilities)",
(BITS (*)[]) text, sizeof text / sizeof text [0]
} ;
static char szBuffer [80] ;
BITS (*pbits) [] = bitinfo [nType].pbits ;
short nDevCaps = GetDeviceCaps (hdcInfo, bitinfo [nType].nIndex) ;
short i ;
TextOut (hdc, cxChar, cyChar, bitinfo [nType].szTitle,
strlen (bitinfo [nType].szTitle)) ;
for (i = 0 ; i < bitinfo [nType].nSize ; i++)
TextOut (hdc, cxChar, (i + 3) * cyChar, szBuffer,
sprintf (szBuffer, "%-16s %s %-32s %3s",
(*pbits)[i].szMask, "Can do", (*pbits)[i].szDesc,
nDevCaps & (*pbits)[i].nMask ? "Yes" : "No")) ;
}
DEVCAPS1.C
CD-ROM Disc Path: \SAMPCODE\PROGWIN\CHAP11\DEVCAPS1.C
/*------------------------------------------------------
DEVCAPS1.C -- Displays Device Capability Information
(c) Charles Petzold, 1990
------------------------------------------------------*/
#include <windows.h>
#include <string.h>
#include "devcaps1.h"
void DoBasicInfo (HDC, HDC, short, short) ; // in DEVCAPS.C
void DoOtherInfo (HDC, HDC, short, short) ;
void DoBitCodedCaps (HDC, HDC, short, short, short) ;
long FAR PASCAL WndProc (HWND, WORD, WORD, LONG) ;
int PASCAL WinMain (HANDLE hInstance, HANDLE hPrevInstance,
LPSTR lpszCmdLine, int nCmdShow)
{
static char szAppName[] = "DevCaps" ;
HWND hwnd ;
MSG msg ;
WNDCLASS wndclass ;
if (!hPrevInstance)
{
wndclass.style = CS_HREDRAW | CS_VREDRAW;
wndclass.lpfnWndProc = WndProc ;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hInstance = hInstance ;
wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = GetStockObject (WHITE_BRUSH) ;
wndclass.lpszMenuName = szAppName ;
wndclass.lpszClassName = szAppName ;
!RegisterClass (&wndclass) ;
}
hwnd = CreateWindow (szAppName, "Device Capabilities",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL) ;
ShowWindow (hwnd, nCmdShow) ;
UpdateWindow (hwnd) ;
while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
return msg.wParam ;
}
HDC GetPrinterIC ()
{
char szPrinter [64] ;
char *szDevice, *szDriver, *szOutput ;
GetProfileString ("windows", "device", "", szPrinter, 64) ;
if ((szDevice = strtok (szPrinter, "," )) &&
(szDriver = strtok (NULL, ", ")) &&
(szOutput = strtok (NULL, ", ")))
return CreateIC (szDriver, szDevice, szOutput, NULL) ;
return NULL ;
}
long FAR PASCAL WndProc (HWND hwnd, WORD message, WORD wParam, LONG lParam)
{
static short cxChar, cyChar, nCurrentDevice = IDM_SCREEN,
nCurrentInfo = IDM_BASIC ;
HDC hdc, hdcInfo ;
HMENU hMenu ;
PAINTSTRUCT ps ;
TEXTMETRIC tm ;
switch (message)
{
case WM_CREATE:
hdc = GetDC (hwnd) ;
SelectObject (hdc, GetStockObject (SYSTEM_FIXED_FONT)) ;
GetTextMetrics (hdc, &tm) ;
cxChar = tm.tmAveCharWidth ;
cyChar = tm.tmHeight + tm.tmExternalLeading ;
ReleaseDC (hwnd, hdc) ;
return 0 ;
case WM_COMMAND:
hMenu = GetMenu (hwnd) ;
switch (wParam)
{
case IDM_SCREEN:
case IDM_PRINTER:
CheckMenuItem (hMenu, nCurrentDevice, MF_UNCHECKED)
nCurrentDevice = wParam ;
CheckMenuItem (hMenu, nCurrentDevice, MF_CHECKED) ;
InvalidateRect (hwnd, NULL, TRUE) ;
return 0 ;
case IDM_BASIC:
case IDM_OTHER:
case IDM_CURVE:
case IDM_LINE:
case IDM_POLY:
case IDM_TEXT:
CheckMenuItem (hMenu, nCurrentInfo, MF_UNCHECKED) ;
nCurrentInfo = wParam ;
CheckMenuItem (hMenu, nCurrentInfo, MF_CHECKED) ;
InvalidateRect (hwnd, NULL, TRUE) ;
return 0 ;
}
break ;
case WM_DEVMODECHANGE:
InvalidateRect (hwnd, NULL, TRUE) ;
return 0 ;
case WM_PAINT:
hdc = BeginPaint (hwnd, &ps) ;
SelectObject (hdc, GetStockObject (SYSTEM_FIXED_FONT)) ;
if (nCurrentDevice == IDM_SCREEN)
hdcInfo = CreateIC ("DISPLAY", NULL, NULL, NULL) ;
else
hdcInfo = GetPrinterIC () ;
if (hdcInfo)
{
switch (nCurrentInfo)
{
case IDM_BASIC:
DoBasicInfo (hdc, hdcInfo, cxChar, cyChar) ;
break ;
case IDM_OTHER:
DoOtherInfo (hdc, hdcInfo, cxChar, cyChar) ;
break ;
case IDM_CURVE:
case IDM_LINE:
case IDM_POLY:
case IDM_TEXT:
DoBitCodedCaps (hdc, hdcInfo, cxChar, cyChar,
nCurrentInfo - IDM_CURVE) ;
break ;
}
DeleteDC (hdcInfo) ;
}
EndPaint (hwnd, &ps) ;
return 0 ;
case WM_DESTROY:
PostQuitMessage (0) ;
return 0 ;
}
return DefWindowProc (hwnd, message, wParam, lParam) ;
}
DEVCAPS2.C
CD-ROM Disc Path: \SAMPCODE\PROGWIN\CHAP15\DEVCAPS2.C
/*------------------------------------------------------------------
DEVCAPS2.C -- Displays Device Capability Information (Version 2)
(c) Charles Petzold, 1990
------------------------------------------------------------------*/
#include <windows.h>
#include <string.h>
#include "devcaps2.h"
void DoBasicInfo (HDC, HDC, short, short) ; // in DEVCAPS.C
void DoOtherInfo (HDC, HDC, short, short) ;
void DoBitCodedCaps (HDC, HDC, short, short, short) ;
typedef VOID (FAR PASCAL *DEVMODEPROC) (HWND, HANDLE, LPSTR, LPSTR) ;
long FAR PASCAL WndProc (HWND, WORD, WORD, LONG) ;
int PASCAL WinMain (HANDLE hInstance, HANDLE hPrevInstance,
LPSTR lpszCmdLine, int nCmdShow)
{
static char szAppName[] = "DevCaps2" ;
HWND hwnd ;
MSG msg ;
WNDCLASS wndclass ;
if (!hPrevInstance)
{
wndclass.style = CS_HREDRAW | CS_VREDRAW;
wndclass.lpfnWndProc = WndProc ;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hInstance = hInstance ;
wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = GetStockObject (WHITE_BRUSH) ;
wndclass.lpszMenuName = szAppName ;
wndclass.lpszClassName = szAppName ;
RegisterClass (&wndclass) ;
}
hwnd = CreateWindow (szAppName, NULL,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL) ;
ShowWindow (hwnd, nCmdShow) ;
UpdateWindow (hwnd) ;
while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
return msg.wParam ;
}
void DoEscSupport (HDC hdc, HDC hdcInfo, short cxChar, short cyChar)
{
static struct
{
char *szEscCode ;
short nEscCode ;
}
esc [] =
{
"NEWFRAME", NEWFRAME,
"ABORTDOC", ABORTDOC,
"NEXTBAND", NEXTBAND,
"SETCOLORTABLE", SETCOLORTABLE,
"GETCOLORTABLE", GETCOLORTABLE,
"FLUSHOUTPUT", FLUSHOUTPUT,
"DRAFTMODE", DRAFTMODE,
"QUERYESCSUPPORT", QUERYESCSUPPORT,
"SETABORTPROC", SETABORTPROC,
"STARTDOC", STARTDOC,
"ENDDOC", ENDDOC,
"GETPHYSPAGESIZE", GETPHYSPAGESIZE,
"GETPRINTINGOFFSET", GETPRINTINGOFFSET,
"GETSCALINGFACTOR", GETSCALINGFACTOR } ;
static char *szYesNo [] = { "Yes", "No" } ;
char szBuffer [32] ;
POINT pt ;
short n, nReturn ;
TextOut (hdc, cxChar, cyChar, "Escape Support", 14) ;
for (n = 0 ; n < sizeof esc / sizeof esc [0] ; n++)
{
nReturn = Escape (hdcInfo, QUERYESCSUPPORT, 1,
(LPSTR) & esc[n].nEscCode, NULL) ;
TextOut (hdc, 6 * cxChar, (n + 3) * cyChar, szBuffer,
wsprintf (szBuffer, "%-24s %3s", (LPSTR) esc[n].szEscCode,
(LPSTR) szYesNo [nReturn > 0 ? 0 : 1])) ;
if (nReturn > 0 && esc[n].nEscCode >= GETPHYSPAGESIZE
&& esc[n].nEscCode <= GETSCALINGFACTOR)
{
Escape (hdcInfo, esc[n].nEscCode, 0, NULL, (LPSTR) &pt) ;
TextOut (hdc, 36 * cxChar, (n + 3) * cyChar, szBuffer,
wsprintf (szBuffer, "(%u,%u)", pt.x, pt.y)) ;
}
}
}
long FAR PASCAL WndProc (HWND hwnd, WORD message, WORD wParam, LONG lParam)
{
static char szAllDevices [4096], szDevice [32], szDriver [16],
szDriverFile [16], szWindowText [64] ;
static HANDLE hLibrary ;
static short n, cxChar, cyChar, nCurrentDevice = IDM_SCREEN,
nCurrentInfo = IDM_BASIC ;
char *szOutput, *szPtr ;
DEVMODEPROC lpfnDM ;
HDC hdc, hdcInfo ;
HMENU hMenu ;
PAINTSTRUCT ps ;
TEXTMETRIC tm ;
switch (message)
{
case WM_CREATE:
hdc = GetDC (hwnd) ;
SelectObject (hdc, GetStockObject (SYSTEM_FIXED_FONT)) ;
GetTextMetrics (hdc, &tm) ;
cxChar = tm.tmAveCharWidth ;
cyChar = tm.tmHeight + tm.tmExternalLeading ;
ReleaseDC (hwnd, hdc) ;
lParam = NULL ;
// fall through
case WM_WININICHANGE:
if (lParam != NULL && lstrcmp ((LPSTR) lParam, "devices") != 0
return 0 ;
hMenu = GetSubMenu (GetMenu (hwnd), 0) ;
while (GetMenuItemCount (hMenu) > 1)
DeleteMenu (hMenu, 1, MF_BYPOSITION) ;
GetProfileString ("devices", NULL, "", szAllDevices,
sizeof szAllDevices) ;
n = IDM_SCREEN + 1 ;
szPtr = szAllDevices ;
while (*szPtr)
{
AppendMenu (hMenu, n % 16 ? 0 : MF_MENUBARBREAK, n, szPtr
n++ ;
szPtr += strlen (szPtr) + 1 ;
}
AppendMenu (hMenu, MF_SEPARATOR, 0, NULL) ;
AppendMenu (hMenu, 0, IDM_DEVMODE, "Device Mode") ;
wParam = IDM_SCREEN ;
// fall through
case WM_COMMAND:
hMenu = GetMenu (hwnd) ;
if (wParam < IDM_DEVMODE) // IDM_SCREEN & Printers
{
CheckMenuItem (hMenu, nCurrentDevice, MF_UNCHECKED) ;
nCurrentDevice = wParam ;
CheckMenuItem (hMenu, nCurrentDevice, MF_CHECKED) ;
}
else if (wParam == IDM_DEVMODE)
{
GetMenuString (hMenu, nCurrentDevice, szDevice,
sizeof szDevice, MF_BYCOMMAND) ;
GetProfileString ("devices", szDevice, "",
szDriver, sizeof szDriver) ;
szOutput = strtok (szDriver, ", ") ;
strcat (strcpy (szDriverFile, szDriver), ".DRV") ;
if (hLibrary >= 32)
FreeLibrary (hLibrary) ;
hLibrary = LoadLibrary (szDriverFile) ;
if (hLibrary >= 32)
{
lpfnDM = GetProcAddress (hLibrary, "DEVICEMODE") ;
(*lpfnDM) (hwnd, hLibrary, (LPSTR) szDevice,
(LPSTR) szOutput) ;
}
}
else // info menu items
{
CheckMenuItem (hMenu, nCurrentInfo, MF_UNCHECKED) ;
nCurrentInfo = wParam ;
CheckMenuItem (hMenu, nCurrentInfo, MF_CHECKED) ;
}
InvalidateRect (hwnd, NULL, TRUE) ;
return 0 ;
case WM_INITMENUPOPUP:
if (lParam == 0)
EnableMenuItem (GetMenu (hwnd), IDM_DEVMODE,
nCurrentDevice == IDM_SCREEN ?
MF_GRAYED : MF_ENABLED) ;
return 0 ;
case WM_PAINT:
strcpy (szWindowText, "Device Capabilities: ") ;
if (nCurrentDevice == IDM_SCREEN)
{
strcpy (szDriver, "DISPLAY") ;
strcat (szWindowText, szDriver) ;
hdcInfo = CreateIC (szDriver, NULL, NULL, NULL) ;
}
else
{
hMenu = GetMenu (hwnd) ;
GetMenuString (hMenu, nCurrentDevice, szDevice,
sizeof szDevice, MF_BYCOMMAND) ;
GetProfileString ("devices", szDevice, "", szDriver, 10)
szOutput = strtok (szDriver, ", ") ;
strcat (szWindowText, szDevice) ;
hdcInfo = CreateIC (szDriver, szDevice, szOutput, NULL) ;
}
SetWindowText (hwnd, szWindowText) ;
hdc = BeginPaint (hwnd, &ps) ;
SelectObject (hdc, GetStockObject (SYSTEM_FIXED_FONT)) ;
if (hdcInfo)
{
switch (nCurrentInfo)
{
case IDM_BASIC:
DoBasicInfo (hdc, hdcInfo, cxChar, cyChar) ;
break ;
case IDM_OTHER:
DoOtherInfo (hdc, hdcInfo, cxChar, cyChar) ;
break ;
case IDM_CURVE:
case IDM_LINE:
case IDM_POLY:
case IDM_TEXT:
DoBitCodedCaps (hdc, hdcInfo, cxChar, cyChar,
nCurrentInfo - IDM_CURVE) ;
break ;
case IDM_ESC:
DoEscSupport (hdc, hdcInfo, cxChar, cyChar) ;
break ;
}
DeleteDC (hdcInfo) ;
}
EndPaint (hwnd, &ps) ;
return 0 ;
case WM_DESTROY:
if (hLibrary >= 32)
FreeLibrary (hLibrary) ;
PostQuitMessage (0) ;
return 0 ;
}
return DefWindowProc (hwnd, message, wParam, lParam) ;
}
DIGCLOCK.C
CD-ROM Disc Path: \SAMPCODE\PROGWIN\CHAP05\DIGCLOCK.C
/*-----------------------------------------
DIGCLOCK.C -- Digital Clock Program
(c) Charles Petzold, 1990
-----------------------------------------*/
#include <windows.h>
#include <time.h>
#define ID_TIMER 1
#define YEAR (datetime->tm_year % 100)
#define MONTH (datetime->tm_mon + 1)
#define MDAY (datetime->tm_mday)
#define WDAY (datetime->tm_wday)
#define HOUR (datetime->tm_hour)
#define MIN (datetime->tm_min)
#define SEC (datetime->tm_sec)
long FAR PASCAL WndProc (HWND, WORD, WORD, LONG);
void SizeTheWindow (short *, short *, short *, short *) ;
char sDate [2], sTime [2], sAMPM [2][5] ;
int iDate, iTime ;
int PASCAL WinMain (HANDLE hInstance, HANDLE hPrevInstance,
LPSTR lpszCmdLine, int nCmdShow)
{
static char szAppName[] = "DigClock" ;
HWND hwnd;
MSG msg;
short xStart, yStart, xClient, yClient ;
WNDCLASS wndclass ;
if (!hPrevInstance)
{
wndclass.style = CS_HREDRAW | CS_VREDRAW;
wndclass.lpfnWndProc = WndProc ;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hInstance = hInstance ;
wndclass.hIcon = NULL ;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = GetStockObject (WHITE_BRUSH) ;
wndclass.lpszMenuName = NULL ;
wndclass.lpszClassName = szAppName ;
RegisterClass (&wndclass) ;
}
SizeTheWindow (&xStart, &yStart, &xClient, &yClient) ;
hwnd = CreateWindow (szAppName, szAppName,
WS_POPUP | WS_DLGFRAME | WS_SYSMENU,
xStart, yStart,
xClient, yClient,
NULL, NULL, hInstance, NULL) ;
if (!SetTimer (hwnd, ID_TIMER, 1000, NULL))
{
MessageBox (hwnd, "Too many clocks or timers!", szAppName,
MB_ICONEXCLAMATION | MB_OK) ;
return FALSE ;
}
ShowWindow (hwnd, SW_SHOWNOACTIVATE) ;
UpdateWindow (hwnd);
while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
return msg.wParam;
}
void SizeTheWindow (short *pxStart, short *pyStart,
short *pxClient, short *pyClient)
{
HDC hdc ;
TEXTMETRIC tm ;
hdc = CreateIC ("DISPLAY", NULL, NULL, NULL) ;
GetTextMetrics (hdc, &tm) ;
DeleteDC (hdc) ;
*pxClient = 2 * GetSystemMetrics (SM_CXDLGFRAME) + 16*tm.tmAveCharWidth
*pxStart = GetSystemMetrics (SM_CXSCREEN) - *pxClient ;
*pyClient = 2 * GetSystemMetrics (SM_CYDLGFRAME) + 2*tm.tmHeight ;
*pyStart = GetSystemMetrics (SM_CYSCREEN) - *pyClient ;
}
void SetInternational (void)
{
static char cName [] = "intl" ;
iDate = GetProfileInt (cName, "iDate", 0) ;
iTime = GetProfileInt (cName, "iTime", 0) ;
GetProfileString (cName, "sDate", "/", sDate, 2) ;
GetProfileString (cName, "sTime", ":", sTime, 2) ;
GetProfileString (cName, "s1159", "AM", sAMPM [0], 5) ;
GetProfileString (cName, "s2359", "PM", sAMPM [1], 5) ;
}
void WndPaint (HWND hwnd, HDC hdc)
{
static char szWday[] = "Sun\0Mon\0Tue\0Wed\0Thu\0Fri\0Sat" ;
char cBuffer[40] ;
long lTime ;
RECT rect ;
short nLength ;
struct tm *datetime ;
time (&lTime) ;
datetime = localtime (&lTime) ;
nLength = wsprintf (cBuffer, " %s %d%s%02d%s%02d \r\n",
(LPSTR) szWday + 4 * WDAY,
iDate == 1 ? MDAY : iDate == 2 ? YEAR : MONTH, (LPSTR) sDate
iDate == 1 ? MONTH : iDate == 2 ? MONTH : MDAY, (LPSTR) sDate
iDate == 1 ? YEAR : iDate == 2 ? MDAY : YEAR) ;
if (iTime == 1)
nLength += wsprintf (cBuffer + nLength, " %02d%s%02d%s%02d ",
HOUR, (LPSTR) sTime, MIN, (LPSTR) sTime, SEC)
else
nLength += wsprintf (cBuffer + nLength, " %d%s%02d%s%02d %s ",
(HOUR % 12) ? (HOUR % 12) : 12,
(LPSTR) sTime, MIN, (LPSTR) sTime, SEC,
(LPSTR) sAMPM [HOUR / 12]) ;
GetClientRect (hwnd, &rect) ;
DrawText (hdc, cBuffer, -1, &rect, DT_CENTER | DT_NOCLIP) ;
}
long FAR PASCAL WndProc (HWND hwnd, WORD message, WORD wParam, LONG lParam)
{
HDC hdc ;
PAINTSTRUCT ps;
switch (message)
{
case WM_CREATE :
SetInternational () ;
return 0 ;
case WM_TIMER :
InvalidateRect (hwnd, NULL, FALSE) ;
return 0 ;
case WM_PAINT :
hdc = BeginPaint (hwnd, &ps) ;
WndPaint (hwnd, hdc) ;
EndPaint (hwnd, &ps) ;
return 0 ;
case WM_WININICHANGE :
SetInternational () ;
InvalidateRect (hwnd, NULL, TRUE) ;
return 0 ;
case WM_DESTROY :
KillTimer (hwnd, ID_TIMER) ;
PostQuitMessage (0) ;
return 0 ;
}
return DefWindowProc (hwnd, message, wParam, lParam) ;
}
ENVIRON.C
CD-ROM Disc Path: \SAMPCODE\PROGWIN\CHAP06\ENVIRON.C
/*----------------------------------------
ENVIRON.C -- Environment List Box
(c) Charles Petzold, 1990
----------------------------------------*/
#include <windows.h>
#include <stdlib.h>
#include <string.h>
#define MAXENV 4096
long FAR PASCAL WndProc (HWND, WORD, WORD, LONG) ;
int PASCAL WinMain (HANDLE hInstance, HANDLE hPrevInstance,
LPSTR lpszCmdLine, int nCmdShow)
{
static char szAppName[] = "Environ" ;
HWND hwnd ;
MSG msg ;
WNDCLASS wndclass ;
if (!hPrevInstance)
{
wndclass.style = CS_HREDRAW | CS_VREDRAW ;
wndclass.lpfnWndProc = WndProc ;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hInstance = hInstance ;
wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = COLOR_WINDOW + 1 ;
wndclass.lpszMenuName = NULL ;
wndclass.lpszClassName = szAppName ;
RegisterClass (&wndclass) ;
}
hwnd = CreateWindow (szAppName, "Environment List Box",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL) ;
ShowWindow (hwnd, nCmdShow) ;
UpdateWindow (hwnd) ;
while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
return msg.wParam ;
}
long FAR PASCAL WndProc (HWND hwnd, WORD message, WORD wParam, LONG lParam)
{
static char szBuffer [MAXENV + 1] ;
static HWND hwndList, hwndText ;
HDC hdc ;
TEXTMETRIC tm ;
WORD n ;
switch (message)
{
case WM_CREATE:
hdc = GetDC (hwnd) ;
GetTextMetrics (hdc, &tm) ;
ReleaseDC (hwnd, hdc) ;
hwndList = CreateWindow ("listbox", NULL,
WS_CHILD | WS_VISIBLE | LBS_STANDARD,
tm.tmAveCharWidth, tm.tmHeight * 3,
tm.tmAveCharWidth * 16 +
GetSystemMetrics (SM_CXVSCROLL),
tm.tmHeight * 5,
hwnd, 1,
GetWindowWord (hwnd, GWW_HINSTANCE), NULL) ;
hwndText = CreateWindow ("static", NULL,
WS_CHILD | WS_VISIBLE | SS_LEFT,
tm.tmAveCharWidth, tm.tmHeight,
tm.tmAveCharWidth * MAXENV, tm.tmHeight,
hwnd, 2,
GetWindowWord (hwnd, GWW_HINSTANCE), NULL) ;
for (n = 0 ; environ[n] ; n++)
{
if (strlen (environ [n]) > MAXENV)
continue ;
*strchr (strcpy (szBuffer, environ [n]), '=') = '\0' ;
SendMessage (hwndList, LB_ADDSTRING, 0,
(LONG) (LPSTR) szBuffer) ;
}
return 0 ;
case WM_SETFOCUS:
SetFocus (hwndList) ;
return 0 ;
case WM_COMMAND:
if (wParam == 1 && HIWORD (lParam) == LBN_SELCHANGE)
{
n = (WORD) SendMessage (hwndList, LB_GETCURSEL, 0, 0L) ;
n = (WORD) SendMessage (hwndList, LB_GETTEXT, n,
(LONG) (LPSTR) szBuffer) ;
strcpy (szBuffer + n + 1, getenv (szBuffer)) ;
*(szBuffer + n) = '=' ;
SetWindowText (hwndText, szBuffer) ;
}
return 0 ;
case WM_DESTROY:
PostQuitMessage (0) ;
return 0 ;
}
return DefWindowProc (hwnd, message, wParam, lParam) ;
}
FILEDLG.C
CD-ROM Disc Path: \SAMPCODE\PROGWIN\CHAP10\FILEDLG.C
/*-----------------------------------------------
FILEDLG.C -- Open and Close File Dialog Boxes
-----------------------------------------------*/
#include <windows.h>
#include "filedlg.h"
BOOL FAR PASCAL FileOpenDlgProc (HWND, WORD, WORD, LONG) ;
BOOL FAR PASCAL FileSaveDlgProc (HWND, WORD, WORD, LONG) ;
LPSTR lstrchr (LPSTR str, char ch) ;
LPSTR lstrrchr (LPSTR str, char ch) ;
static char szDefExt [5] ;
static char szFileName [96] ;
static char szFileSpec [16] ;
static POFSTRUCT pof ;
static WORD wFileAttr, wStatus ;
int DoFileOpenDlg (HANDLE hInst, HWND hwnd, char *szFileSpecIn,
char *szDefExtIn, WORD wFileAttrIn,
char *szFileNameOut, POFSTRUCT pofIn)
{
FARPROC lpfnFileOpenDlgProc ;
int iReturn ;
lstrcpy (szFileSpec, szFileSpecIn) ;
lstrcpy (szDefExt, szDefExtIn) ;
wFileAttr = wFileAttrIn ;
pof = pofIn ;
lpfnFileOpenDlgProc = MakeProcInstance (FileOpenDlgProc, hInst) ;
iReturn = DialogBox (hInst, "FileOpen", hwnd, lpfnFileOpenDlgProc) ;
FreeProcInstance (lpfnFileOpenDlgProc) ;
lstrcpy (szFileNameOut, szFileName) ;
return iReturn ;
}
int DoFileSaveDlg (HANDLE hInst, HWND hwnd, char *szFileSpecIn,
char *szDefExtIn, WORD *pwStatusOut,
char *szFileNameOut, POFSTRUCT pofIn)
{
FARPROC lpfnFileSaveDlgProc ;
int iReturn ;
lstrcpy (szFileSpec, szFileSpecIn) ;
lstrcpy (szDefExt, szDefExtIn) ;
pof = pofIn ;
lpfnFileSaveDlgProc = MakeProcInstance (FileSaveDlgProc, hInst) ;
iReturn = DialogBox (hInst, "FileSave", hwnd, lpfnFileSaveDlgProc) ;
FreeProcInstance (lpfnFileSaveDlgProc) ;
lstrcpy (szFileNameOut, szFileName) ;
*pwStatusOut = wStatus ;
return iReturn ;
}
BOOL FAR PASCAL FileOpenDlgProc (HWND hDlg, WORD message,
WORD wParam, LONG lParam)
{
char cLastChar ;
short nEditLen ;
switch (message)
{
case WM_INITDIALOG:
SendDlgItemMessage (hDlg, IDD_FNAME, EM_LIMITTEXT, 80, 0L) ;
DlgDirList (hDlg, szFileSpec, IDD_FLIST, IDD_FPATH, wFileAttr) ;
SetDlgItemText (hDlg, IDD_FNAME, szFileSpec) ;
return TRUE ;
case WM_COMMAND:
switch (wParam)
{
case IDD_FLIST:
switch (HIWORD (lParam))
{
case LBN_SELCHANGE:
if (DlgDirSelect (hDlg, szFileName, IDD_FLIST))
lstrcat (szFileName, szFileSpec) ;
SetDlgItemText (hDlg, IDD_FNAME, szFileName) ;
return TRUE ;
case LBN_DBLCLK:
if (DlgDirSelect (hDlg, szFileName, IDD_FLIST))
{
lstrcat (szFileName, szFileSpec) ;
DlgDirList (hDlg, szFileName, IDD_FLIST, IDD_FPATH,
wFileAttr) ;
SetDlgItemText (hDlg, IDD_FNAME, szFileSpec) ;
}
else
{
SetDlgItemText (hDlg, IDD_FNAME, szFileName) ;
SendMessage (hDlg, WM_COMMAND, IDOK, 0L) ;
}
return TRUE ;
}
break ;
case IDD_FNAME:
if (HIWORD (lParam) == EN_CHANGE)
EnableWindow (GetDlgItem (hDlg, IDOK),
(BOOL) SendMessage (LOWORD (lParam),
WM_GETTEXTLENGTH, 0, 0L)) ;
return TRUE ;
case IDOK:
GetDlgItemText (hDlg, IDD_FNAME, szFileName, 80) ;
nEditLen = lstrlen (szFileName) ;
cLastChar = *AnsiPrev (szFileName, szFileName + nEditLen) ;
if (cLastChar == '\\' || cLastChar == ':')
lstrcat (szFileName, szFileSpec) ;
if (lstrchr (szFileName, '*') || lstrchr (szFileName, '?'))
{
if (DlgDirList (hDlg, szFileName, IDD_FLIST,
IDD_FPATH, wFileAttr))
{
lstrcpy (szFileSpec, szFileName) ;
SetDlgItemText (hDlg, IDD_FNAME, szFileSpec) ;
}
else
MessageBeep (0) ;
return TRUE ;
}
lstrcat (lstrcat (szFileName, "\\"), szFileSpec) ;
if (DlgDirList (hDlg, szFileName, IDD_FLIST,
IDD_FPATH, wFileAttr))
{
lstrcpy (szFileSpec, szFileName) ;
SetDlgItemText (hDlg, IDD_FNAME, szFileSpec) ;
return TRUE ;
}
szFileName [nEditLen] = '\0' ;
if (-1 == OpenFile (szFileName, pof, OF_READ | OF_EXIST))
{
lstrcat (szFileName, szDefExt) ;
if (-1 == OpenFile (szFileName, pof, OF_READ | OF_EXIST))
{
MessageBeep (0) ;
return TRUE ;
}
}
lstrcpy (szFileName,
AnsiNext (lstrrchr (pof->szPathName, '\\'))) ;
OemToAnsi (szFileName, szFileName) ;
EndDialog (hDlg, TRUE) ;
return TRUE ;
case IDCANCEL:
EndDialog (hDlg, FALSE) ;
return TRUE ;
}
}
return FALSE ;
}
BOOL FAR PASCAL FileSaveDlgProc (HWND hDlg, WORD message,
WORD wParam, LONG lParam)
{
switch (message)
{
case WM_INITDIALOG:
SendDlgItemMessage (hDlg, IDD_FNAME, EM_LIMITTEXT, 80, 0L) ;
DlgDirList (hDlg, szFileSpec, 0, IDD_FPATH, 0) ;
SetDlgItemText (hDlg, IDD_FNAME, szFileSpec) ;
return TRUE ;
case WM_COMMAND:
switch (wParam)
{
case IDD_FNAME:
if (HIWORD (lParam) == EN_CHANGE)
EnableWindow (GetDlgItem (hDlg, IDOK),
(BOOL) SendMessage (LOWORD (lParam),
WM_GETTEXTLENGTH, 0, 0L)) ;
return TRUE ;
case IDOK:
GetDlgItemText (hDlg, IDD_FNAME, szFileName, 80) ;
if (-1 == OpenFile (szFileName, pof, OF_PARSE))
{
MessageBeep (0) ;
return TRUE ;
}
if (!lstrchr (AnsiNext (lstrrchr (pof->szPathName, '\\')),
'.'))
lstrcat (szFileName, szDefExt) ;
if (-1 != OpenFile (szFileName, pof, OF_WRITE | OF_EXIST))
wStatus = 1 ;
else if (-1 != OpenFile (szFileName, pof,
OF_CREATE | OF_EXIST))
wStatus = 0 ;
else
{
MessageBeep (0) ;
return TRUE ;
}
lstrcpy (szFileName,
AnsiNext (lstrrchr (pof->szPathName, '\\'))) ;
OemToAnsi (szFileName, szFileName) ;
EndDialog (hDlg, TRUE) ;
return TRUE ;
case IDCANCEL:
EndDialog (hDlg, FALSE) ;
return TRUE ;
}
}
return FALSE ;
}
LPSTR lstrchr (LPSTR str, char ch)
{
while (*str)
{
if (ch == *str)
return str ;
str = AnsiNext (str) ;
}
return NULL ;
}
LPSTR lstrrchr (LPSTR str, char ch)
{
LPSTR strl = str + lstrlen (str) ;
do
{
if (ch == *strl)
return strl ;
strl = AnsiPrev (str, strl) ;
}
while (strl > str) ;
return NULL ;
}
FILEDLG.C
CD-ROM Disc Path: \SAMPCODE\PROGWIN\CHAP15\FILEDLG.C
/*-----------------------------------------------
FILEDLG.C -- Open and Close File Dialog Boxes
-----------------------------------------------*/
#include <windows.h>
#include "filedlg.h"
BOOL FAR PASCAL FileOpenDlgProc (HWND, WORD, WORD, LONG) ;
BOOL FAR PASCAL FileSaveDlgProc (HWND, WORD, WORD, LONG) ;
LPSTR lstrchr (LPSTR str, char ch) ;
LPSTR lstrrchr (LPSTR str, char ch) ;
static char szDefExt [5] ;
static char szFileName [96] ;
static char szFileSpec [16] ;
static POFSTRUCT pof ;
static WORD wFileAttr, wStatus ;
int DoFileOpenDlg (HANDLE hInst, HWND hwnd, char *szFileSpecIn,
char *szDefExtIn, WORD wFileAttrIn,
char *szFileNameOut, POFSTRUCT pofIn)
{
FARPROC lpfnFileOpenDlgProc ;
int iReturn ;
lstrcpy (szFileSpec, szFileSpecIn) ;
lstrcpy (szDefExt, szDefExtIn) ;
wFileAttr = wFileAttrIn ;
pof = pofIn ;
lpfnFileOpenDlgProc = MakeProcInstance (FileOpenDlgProc, hInst) ;
iReturn = DialogBox (hInst, "FileOpen", hwnd, lpfnFileOpenDlgProc) ;
FreeProcInstance (lpfnFileOpenDlgProc) ;
lstrcpy (szFileNameOut, szFileName) ;
return iReturn ;
}
int DoFileSaveDlg (HANDLE hInst, HWND hwnd, char *szFileSpecIn,
char *szDefExtIn, WORD *pwStatusOut,
char *szFileNameOut, POFSTRUCT pofIn)
{
FARPROC lpfnFileSaveDlgProc ;
int iReturn ;
lstrcpy (szFileSpec, szFileSpecIn) ;
lstrcpy (szDefExt, szDefExtIn) ;
pof = pofIn ;
lpfnFileSaveDlgProc = MakeProcInstance (FileSaveDlgProc, hInst) ;
iReturn = DialogBox (hInst, "FileSave", hwnd, lpfnFileSaveDlgProc) ;
FreeProcInstance (lpfnFileSaveDlgProc) ;
lstrcpy (szFileNameOut, szFileName) ;
*pwStatusOut = wStatus ;
return iReturn ;
}
BOOL FAR PASCAL FileOpenDlgProc (HWND hDlg, WORD message,
WORD wParam, LONG lParam)
{
char cLastChar ;
short nEditLen ;
switch (message)
{
case WM_INITDIALOG:
SendDlgItemMessage (hDlg, IDD_FNAME, EM_LIMITTEXT, 80, 0L) ;
DlgDirList (hDlg, szFileSpec, IDD_FLIST, IDD_FPATH, wFileAttr) ;
SetDlgItemText (hDlg, IDD_FNAME, szFileSpec) ;
return TRUE ;
case WM_COMMAND:
switch (wParam)
{
case IDD_FLIST:
switch (HIWORD (lParam))
{
case LBN_SELCHANGE:
if (DlgDirSelect (hDlg, szFileName, IDD_FLIST))
lstrcat (szFileName, szFileSpec) ;
SetDlgItemText (hDlg, IDD_FNAME, szFileName) ;
return TRUE ;
case LBN_DBLCLK:
if (DlgDirSelect (hDlg, szFileName, IDD_FLIST))
{
lstrcat (szFileName, szFileSpec) ;
DlgDirList (hDlg, szFileName, IDD_FLIST, IDD_FPATH,
wFileAttr) ;
SetDlgItemText (hDlg, IDD_FNAME, szFileSpec) ;
}
else
{
SetDlgItemText (hDlg, IDD_FNAME, szFileName) ;
SendMessage (hDlg, WM_COMMAND, IDOK, 0L) ;
}
return TRUE ;
}
break ;
case IDD_FNAME:
if (HIWORD (lParam) == EN_CHANGE)
EnableWindow (GetDlgItem (hDlg, IDOK),
(BOOL) SendMessage (LOWORD (lParam),
WM_GETTEXTLENGTH, 0, 0L)) ;
return TRUE ;
case IDOK:
GetDlgItemText (hDlg, IDD_FNAME, szFileName, 80) ;
nEditLen = lstrlen (szFileName) ;
cLastChar = *AnsiPrev (szFileName, szFileName + nEditLen) ;
if (cLastChar == '\\' || cLastChar == ':')
lstrcat (szFileName, szFileSpec) ;
if (lstrchr (szFileName, '*') || lstrchr (szFileName, '?'))
{
if (DlgDirList (hDlg, szFileName, IDD_FLIST,
IDD_FPATH, wFileAttr))
{
lstrcpy (szFileSpec, szFileName) ;
SetDlgItemText (hDlg, IDD_FNAME, szFileSpec) ;
}
else
MessageBeep (0) ;
return TRUE ;
}
lstrcat (lstrcat (szFileName, "\\"), szFileSpec) ;
if (DlgDirList (hDlg, szFileName, IDD_FLIST,
IDD_FPATH, wFileAttr))
{
lstrcpy (szFileSpec, szFileName) ;
SetDlgItemText (hDlg, IDD_FNAME, szFileSpec) ;
return TRUE ;
}
szFileName [nEditLen] = '\0' ;
if (-1 == OpenFile (szFileName, pof, OF_READ | OF_EXIST))
{
lstrcat (szFileName, szDefExt) ;
if (-1 == OpenFile (szFileName, pof, OF_READ | OF_EXIST))
{
MessageBeep (0) ;
return TRUE ;
}
}
lstrcpy (szFileName,
AnsiNext (lstrrchr (pof->szPathName, '\\'))) ;
OemToAnsi (szFileName, szFileName) ;
EndDialog (hDlg, TRUE) ;
return TRUE ;
case IDCANCEL:
EndDialog (hDlg, FALSE) ;
return TRUE ;
}
}
return FALSE ;
}
BOOL FAR PASCAL FileSaveDlgProc (HWND hDlg, WORD message,
WORD wParam, LONG lParam)
{
switch (message)
{
case WM_INITDIALOG:
SendDlgItemMessage (hDlg, IDD_FNAME, EM_LIMITTEXT, 80, 0L) ;
DlgDirList (hDlg, szFileSpec, 0, IDD_FPATH, 0) ;
SetDlgItemText (hDlg, IDD_FNAME, szFileSpec) ;
return TRUE ;
case WM_COMMAND:
switch (wParam)
{
case IDD_FNAME:
if (HIWORD (lParam) == EN_CHANGE)
EnableWindow (GetDlgItem (hDlg, IDOK),
(BOOL) SendMessage (LOWORD (lParam),
WM_GETTEXTLENGTH, 0, 0L)) ;
return TRUE ;
case IDOK:
GetDlgItemText (hDlg, IDD_FNAME, szFileName, 80) ;
if (-1 == OpenFile (szFileName, pof, OF_PARSE))
{
MessageBeep (0) ;
return TRUE ;
}
if (!lstrchr (AnsiNext (lstrrchr (pof->szPathName, '\\')),
'.'))
lstrcat (szFileName, szDefExt) ;
if (-1 != OpenFile (szFileName, pof, OF_WRITE | OF_EXIST))
wStatus = 1 ;
else if (-1 != OpenFile (szFileName, pof,
OF_CREATE | OF_EXIST))
wStatus = 0 ;
else
{
MessageBeep (0) ;
return TRUE ;
}
lstrcpy (szFileName,
AnsiNext (lstrrchr (pof->szPathName, '\\'))) ;
OemToAnsi (szFileName, szFileName) ;
EndDialog (hDlg, TRUE) ;
return TRUE ;
case IDCANCEL:
EndDialog (hDlg, FALSE) ;
return TRUE ;
}
}
return FALSE ;
}
LPSTR lstrchr (LPSTR str, char ch)
{
while (*str)
{
if (ch == *str)
return str ;
str = AnsiNext (str) ;
}
return NULL ;
}
LPSTR lstrrchr (LPSTR str, char ch)
{
LPSTR strl = str + lstrlen (str) ;
do
{
if (ch == *strl)
return strl ;
strl = AnsiPrev (str, strl) ;
}
while (strl > str) ;
return NULL ;
}
FONTLIST.C
CD-ROM Disc Path: \SAMPCODE\PROGWIN\CHAP14\FONTLIST.C
/*-----------------------------------------
FONTLIST.C -- Font Enumeration Program
(c) Charles Petzold, 1990
-----------------------------------------*/
#include <windows.h>
#include <string.h>
#include "fontlist.h"
typedef struct
{
GLOBALHANDLE hGMem ;
short nCount ;
}
ENUMER ;
typedef struct
{
short nFontType ;
LOGFONT lf ;
TEXTMETRIC tm ;
}
FONT ;
long FAR PASCAL WndProc (HWND, WORD, WORD, LONG) ;
int FAR PASCAL EnumAllFaces (LPLOGFONT, LPTEXTMETRIC, short, ENUMER FAR *) ;
int FAR PASCAL EnumAllFonts (LPLOGFONT, LPTEXTMETRIC, short, ENUMER FAR *) ;
char szAppName[] = "FontList" ;
int PASCAL WinMain (HANDLE hInstance, HANDLE hPrevInstance,
LPSTR lpszCmdLine, int nCmdShow)
{
HWND hwnd ;
MSG msg ;
WNDCLASS wndclass ;
if (!hPrevInstance)
{
wndclass.style = CS_HREDRAW | CS_VREDRAW;
wndclass.lpfnWndProc = WndProc ;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hInstance = hInstance ;
wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = GetStockObject (WHITE_BRUSH) ;
wndclass.lpszMenuName = szAppName ;
wndclass.lpszClassName = szAppName ;
RegisterClass (&wndclass) ;
}
hwnd = CreateWindow (szAppName, "Font Enumeration",
WS_OVERLAPPEDWINDOW | WS_VSCROLL,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL) ;
ShowWindow (hwnd, nCmdShow) ;
UpdateWindow (hwnd) ;
while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
return msg.wParam ;
}
int FAR PASCAL EnumAllFaces (LPLOGFONT lf, LPTEXTMETRIC tm,
short nFontType, ENUMER FAR *enumer)
{
LPSTR lpFaces ;
if (NULL == GlobalReAlloc (enumer->hGMem,
(DWORD) LF_FACESIZE * (1 + enumer->nCount),
GMEM_MOVEABLE))
return 0 ;
lpFaces = GlobalLock (enumer->hGMem) ;
lstrcpy (lpFaces + enumer->nCount * LF_FACESIZE, lf->lfFaceName) ;
GlobalUnlock (enumer->hGMem) ;
enumer->nCount ++ ;
return 1 ;
}
int FAR PASCAL EnumAllFonts (LPLOGFONT lf, LPTEXTMETRIC tm,
short nFontType, ENUMER FAR *enumer)
{
FONT FAR *font ;
if (NULL == GlobalReAlloc (enumer->hGMem,
(DWORD) sizeof (FONT) * (1 + enumer->nCount),
GMEM_MOVEABLE))
return 0 ;
font = (FONT FAR *) GlobalLock (enumer->hGMem) + enumer->nCount ;
font->nFontType = nFontType ;
font->lf = *lf ;
font->tm = *tm ;
GlobalUnlock (enumer->hGMem) ;
enumer->nCount ++ ;
return 1 ;
}
void Display (HDC hdc, short cxChar, short cyChar, FONT FAR *font)
{
static FONT f ;
static char *szYN [] = { "No", "Yes" } ;
static char *szCS [] = { "ANSI", "?????", "Kanji", "OEM" } ;
static char *szOP [] = { "Default", "String", "Char", "Stroke" }
static char *szCP [] = { "Default", "Char", "Stroke", "?????" }
static char *szQU [] = { "Draft", "Default", "Proof", "?????" }
static char *szP1 [] = { "Default", "Fixed", "Variable", "?????" }
static char *szP2 [] = { "Fixed", "Variable" } ;
static char *szFA [] = { "Don't Care", "Roman", "Swiss", "Modern",
"Script", "Decorative", "?????", "?????" }
static char *szVR [] = { "Stroke", "Raster" } ;
static char *szGD [] = { "GDI", "Device" } ;
static struct
{
short x ;
short y ;
char *szFmt ;
short *pData ;
}
shorts [] =
{
1, 1, "LOGFONT", NULL,
1, 2, "-------", NULL,
1, 3, "Height: %10d", &f.lf.lfHeight,
1, 4, "Width: %10d", &f.lf.lfWidth,
1, 5, "Escapement: %10d", &f.lf.lfEscapement,
1, 6, "Orientation: %10d", &f.lf.lfOrientation,
1, 7, "Weight: %10d", &f.lf.lfWeight,
28, 1, "TEXTMETRIC", NULL,
28, 2, "----------", NULL,
28, 3, "Height: %5d", &f.tm.tmHeight,
28, 4, "Ascent: %5d", &f.tm.tmAscent,
28, 5, "Descent: %5d", &f.tm.tmDescent,
28, 6, "Int. Leading: %5d", &f.tm.tmInternalLeading,
28, 7, "Ext. Leading: %5d", &f.tm.tmExternalLeading,
28, 8, "Ave. Width: %5d", &f.tm.tmAveCharWidth,
28, 9, "Max. Width: %5d", &f.tm.tmMaxCharWidth,
28, 10, "Weight: %5d", &f.tm.tmWeight,
51, 10, "Overhang: %10d", &f.tm.tmOverhang,
51, 11, "Digitized X: %10d", &f.tm.tmDigitizedAspectX,
51, 12, "Digitized Y: %10d", &f.tm.tmDigitizedAspectY
} ;
static struct
{
short x ;
short y ;
char *szFmt ;
BYTE *pData ;
}
bytes [] =
{
51, 3, "First Char: %10d", &f.tm.tmFirstChar,
51, 4, "Last Char: %10d", &f.tm.tmLastChar,
51, 5, "Default Char: %10d", &f.tm.tmDefaultChar,
51, 6, "Break Char: %10d", &f.tm.tmBreakChar
} ;
static struct
{
short x ;
short y ;
char *szFmt ;
BYTE *pData ;
char **szArray ;
short sAnd ;
short sShift ;
}
strings [] =
{
1, 8, "Italic: %10s", &f.lf.lfItalic, szYN, 1, 0
1, 9, "Underline: %10s", &f.lf.lfUnderline, szYN, 1, 0
1, 10, "Strike-Out: %10s", &f.lf.lfStrikeOut, szYN, 1, 0
1, 11, "Char Set: %10s", &f.lf.lfCharSet, szCS, 0xC0, 6
1, 12, "Out Prec: %10s", &f.lf.lfOutPrecision, szOP, 3, 0
1, 13, "Clip Prec: %10s", &f.lf.lfClipPrecision, szCP, 3, 0
1, 14, "Quality: %10s", &f.lf.lfQuality, szQU, 3, 0
1, 15, "Pitch: %10s", &f.lf.lfPitchAndFamily, szP1, 3, 0
1, 16, "Family: %10s", &f.lf.lfPitchAndFamily, szFA, 0x70, 4
28, 11, "Italic: %5s", &f.tm.tmItalic, szYN, 1, 0
28, 12, "Underline: %5s", &f.tm.tmUnderlined, szYN, 1, 0
28, 13, "Strike-Out: %5s", &f.tm.tmStruckOut, szYN, 1, 0
51, 7, "Pitch: %10s", &f.tm.tmPitchAndFamily, szP2, 1, 0
51, 8, "Family: %10s", &f.tm.tmPitchAndFamily, szFA, 0x70, 4
51, 9, "Char Set: %10s", &f.tm.tmCharSet, szCS, 0xC0, 6
36, 15, "Font Type: %6s", (BYTE *) &f.nFontType, szVR, 1, 0
55, 15, "%s", (BYTE *) &f.nFontType, szGD, 2, 1
} ;
char szBuffer [80] ;
int i ;
f = *font ;
for (i = 0 ; i < sizeof shorts / sizeof shorts [0] ; i++)
TextOut (hdc, cxChar * shorts[i].x, cyChar * shorts[i].y, szBuffer,
wsprintf (szBuffer, shorts[i].szFmt,
*shorts[i].pData)) ;
for (i = 0 ; i < sizeof bytes / sizeof bytes [0] ; i++)
TextOut (hdc, cxChar * bytes[i].x, cyChar * bytes[i].y, szBuffer,
wsprintf (szBuffer, bytes[i].szFmt,
*bytes[i].pData)) ;
for (i = 0 ; i < sizeof strings / sizeof strings [0] ; i++)
TextOut (hdc, cxChar * strings[i].x, cyChar * strings[i].y, szBuffe
wsprintf (szBuffer, strings[i].szFmt,
(LPSTR) ((strings[i].szArray)
[(*strings[i].pData & strings[i].sAnd) >>
strings[i].sShift]))) ;
TextOut (hdc, cxChar, cyChar * 17, szBuffer,
wsprintf (szBuffer, "Face Name: %10s",
(LPSTR) f.lf.lfFaceName)) ;
}
HDC GetPrinterIC ()
{
char szPrinter [64] ;
char *szDevice, *szDriver, *szOutput ;
GetProfileString ("windows", "device", "", szPrinter, 64) ;
if ((szDevice = strtok (szPrinter, "," )) &&
(szDriver = strtok (NULL, ", ")) &&
(szOutput = strtok (NULL, ", ")))
return CreateIC (szDriver, szDevice, szOutput, NULL) ;
return NULL ;
}
long FAR PASCAL WndProc (HWND hwnd, WORD message, WORD wParam, LONG lParam)
{
static BOOL bHaveInfo = FALSE ;
static ENUMER enumer1, enumer2 ;
static FARPROC lpfnEnumAllFaces, lpfnEnumAllFonts ;
static short cxChar, cyChar, nCurrent ;
static WORD wCurrentDC = IDM_SCREEN ;
HANDLE hInstance ;
HDC hdc ;
HFONT hFont ;
HMENU hMenu ;
FONT FAR *font ;
LPSTR lpFaces ;
PAINTSTRUCT ps ;
short i ;
TEXTMETRIC tm ;
switch (message)
{
case WM_CREATE:
hInstance = ((LPCREATESTRUCT) lParam)-> hInstance ;
lpfnEnumAllFaces = MakeProcInstance (EnumAllFaces, hInstance)
lpfnEnumAllFonts = MakeProcInstance (EnumAllFonts, hInstance)
hdc = GetDC (hwnd) ;
SelectObject (hdc, GetStockObject (SYSTEM_FIXED_FONT)) ;
GetTextMetrics (hdc, (LPTEXTMETRIC) &tm) ;
cxChar = tm.tmAveCharWidth ;
cyChar = tm.tmHeight + tm.tmExternalLeading ;
ReleaseDC (hwnd, hdc) ;
return 0 ;
case WM_COMMAND:
if (wParam == IDM_EXIT)
{
SendMessage (hwnd, WM_CLOSE, 0, 0L) ;
return 0 ;
}
else if (wParam == wCurrentDC)
return 0 ;
hMenu = GetMenu (hwnd) ;
CheckMenuItem (hMenu, wCurrentDC, MF_UNCHECKED) ;
CheckMenuItem (hMenu, wCurrentDC = wParam, MF_CHECKED) ;
// fall through
case WM_DEVMODECHANGE:
case WM_FONTCHANGE:
bHaveInfo = FALSE ;
InvalidateRect (hwnd, NULL, TRUE) ;
return 0 ;
case WM_PAINT:
if (!bHaveInfo)
{
if (enumer2.hGMem)
GlobalFree (enumer2.hGMem) ;
enumer1.hGMem = GlobalAlloc (GHND, 1L) ;
enumer1.nCount = 0 ;
enumer2.hGMem = GlobalAlloc (GHND, 1L) ;
enumer2.nCount = 0 ;
if (NULL == enumer1.hGMem || NULL == enumer2.hGMem)
goto MEMORY_ERROR ;
if (wCurrentDC == IDM_SCREEN)
hdc = CreateIC ("DISPLAY", NULL, NULL, NULL) ;
else
hdc = GetPrinterIC () ;
if (hdc)
{
if (0 == EnumFonts (hdc, NULL, lpfnEnumAllFaces,
(LPSTR) &enumer1))
goto MEMORY_ERROR ;
lpFaces = GlobalLock (enumer1.hGMem) ;
for (i = 0 ; i < enumer1.nCount ; i++)
if (0 == EnumFonts (hdc,
lpFaces + i * LF_FACESIZE,
lpfnEnumAllFonts,
(LPSTR) &enumer2))
goto MEMORY_ERROR ;
GlobalUnlock (enumer1.hGMem) ;
enumer2.nCount-- ;
DeleteDC (hdc) ;
bHaveInfo = TRUE ;
}
GlobalFree (enumer1.hGMem) ;
SetScrollRange (hwnd, SB_VERT, 0, enumer2.nCount, FALSE)
SetScrollPos (hwnd, SB_VERT, nCurrent = 0, TRUE) ;
}
hdc = BeginPaint (hwnd, &ps) ;
if (bHaveInfo)
{
SelectObject (hdc, GetStockObject (SYSTEM_FIXED_FONT)) ;
font = (FONT FAR *) GlobalLock (enumer2.hGMem) + nCurrent
Display (hdc, cxChar, cyChar, font) ;
hFont = SelectObject (hdc, CreateFontIndirect (&font->lf)
TextOut (hdc, 1 * cxChar, 19 * cyChar,
"AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz
52) ;
GlobalUnlock (enumer2.hGMem) ;
DeleteObject (SelectObject (hdc, hFont)) ;
}
EndPaint (hwnd, &ps) ;
return 0 ;
case WM_KEYDOWN:
switch (wParam)
{
case VK_HOME:
SendMessage (hwnd, WM_VSCROLL, SB_TOP, 0L) ;
break ;
case VK_END:
SendMessage (hwnd, WM_VSCROLL, SB_BOTTOM, 0L) ;
break ;
case VK_LEFT:
case VK_UP:
case VK_PRIOR:
SendMessage (hwnd, WM_VSCROLL, SB_LINEUP, 0L) ;
break ;
case VK_RIGHT:
case VK_DOWN:
case VK_NEXT:
SendMessage (hwnd, WM_VSCROLL, SB_LINEDOWN, 0L) ;
break ;
default:
return 0 ;
}
return 0 ;
case WM_VSCROLL:
switch (wParam)
{
case SB_TOP:
nCurrent = 0 ;
break ;
case SB_BOTTOM:
nCurrent = enumer2.nCount ;
break ;
case SB_LINEUP:
case SB_PAGEUP:
nCurrent -- ;
break ;
case SB_LINEDOWN:
case SB_PAGEDOWN:
nCurrent ++ ;
break ;
case SB_THUMBPOSITION:
nCurrent = LOWORD (lParam) ;
break ;
default:
return 0 ;
}
nCurrent = min (max (0, nCurrent), enumer2.nCount) ;
SetScrollPos (hwnd, SB_VERT, nCurrent, TRUE) ;
InvalidateRect (hwnd, NULL, TRUE) ;
return 0 ;
MEMORY_ERROR:
MessageBox (hwnd, "Cannot allocate memory, must end.",
szAppName, MB_OK | MB_ICONSTOP | MB_SYSTEMMODAL) ;
// fall through
case WM_CLOSE:
DestroyWindow (hwnd) ;
return 0 ;
case WM_DESTROY:
PostQuitMessage (0) ;
return 0 ;
}
return DefWindowProc (hwnd, message, wParam, lParam) ;
}
FORMFEED.C
CD-ROM Disc Path: \SAMPCODE\PROGWIN\CHAP15\FORMFEED.C
/*---------------------------------------------
FORMFEED.C -- Advances printer to next page
(c) Charles Petzold, 1990
---------------------------------------------*/
#include <windows.h>
#include <string.h>
HDC GetPrinterDC (void) ;
int PASCAL WinMain (HANDLE hInstance, HANDLE hPrevInstance,
LPSTR lpszCmdLine, int nCmdShow)
{
static char szMsg [] = "FormFeed" ;
HDC hdcPrint ;
if (hdcPrint = GetPrinterDC ())
{
if (Escape (hdcPrint, STARTDOC, sizeof szMsg - 1, szMsg, NULL) > 0)
if (Escape (hdcPrint, NEWFRAME, 0, NULL, NULL) > 0)
Escape (hdcPrint, ENDDOC, 0, NULL, NULL) ;
DeleteDC (hdcPrint) ;
}
return FALSE ;
}
HDC GetPrinterDC (void)
{
static char szPrinter [80] ;
char *szDevice, *szDriver, *szOutput ;
GetProfileString ("windows", "device", ",,,", szPrinter, 80) ;
if ((szDevice = strtok (szPrinter, "," )) &&
(szDriver = strtok (NULL, ", ")) &&
(szOutput = strtok (NULL, ", ")))
return CreateDC (szDriver, szDevice, szOutput, NULL) ;
return 0 ;
}
FREEMEM.C
CD-ROM Disc Path: \SAMPCODE\PROGWIN\CHAP05\FREEMEM.C
/*------------------------------------------
FREEMEM.C -- Free Memory Display Program
(c) Charles Petzold, 1990
------------------------------------------*/
#include <windows.h>
#include <stdio.h>
#define ID_TIMER 1
long FAR PASCAL WndProc (HWND, WORD, WORD, LONG) ;
int PASCAL WinMain (HANDLE hInstance, HANDLE hPrevInstance,
LPSTR lpszCmdLine, int nCmdShow)
{
static char szAppName[] = "FreeMem" ;
HDC hdc ;
HWND hwnd ;
MSG msg ;
TEXTMETRIC tm ;
WNDCLASS wndclass ;
if (hPrevInstance)
return FALSE ;
wndclass.style = CS_HREDRAW | CS_VREDRAW;
wndclass.lpfnWndProc = WndProc ;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hInstance = hInstance ;
wndclass.hIcon = NULL ;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = GetStockObject (WHITE_BRUSH) ;
wndclass.lpszMenuName = NULL ;
wndclass.lpszClassName = szAppName ;
!RegisterClass (&wndclass) ;
hwnd = CreateWindow (szAppName, "Free Memory",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL) ;
hdc = GetDC (hwnd) ;
GetTextMetrics (hdc, &tm) ;
ReleaseDC (hwnd, hdc) ;
if (4 * tm.tmAveCharWidth > GetSystemMetrics (SM_CXICON) ||
2 * tm.tmHeight > GetSystemMetrics (SM_CYICON))
{
MessageBox (hwnd, "Icon size too small for display!",
szAppName, MB_ICONEXCLAMATION | MB_OK) ;
return FALSE ;
}
if (!SetTimer (hwnd, ID_TIMER, 1000, NULL))
{
MessageBox (hwnd, "Too many clocks or timers!",
szAppName, MB_ICONEXCLAMATION | MB_OK) ;
return FALSE ;
}
ShowWindow (hwnd, SW_SHOWMINNOACTIVE) ;
UpdateWindow (hwnd) ;
while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
return msg.wParam ;
}
long FAR PASCAL WndProc (HWND hwnd, WORD message, WORD wParam, LONG lParam)
{
static DWORD dwFreeMem, dwPrevMem ;
static RECT rect ;
char cBuffer [20] ;
HDC hdc ;
PAINTSTRUCT ps ;
switch (message)
{
case WM_TIMER:
dwFreeMem = GetFreeSpace (0) ;
if (dwFreeMem != dwPrevMem)
InvalidateRect (hwnd, NULL, TRUE) ;
dwPrevMem = dwFreeMem ;
return 0 ;
case WM_SIZE:
GetClientRect (hwnd, &rect) ;
return 0 ;
case WM_PAINT:
hdc = BeginPaint (hwnd, &ps) ;
DrawText (hdc, cBuffer,
sprintf (cBuffer, "%.2f megs",
dwFreeMem / 1024.0 / 1024.0),
&rect, DT_WORDBREAK) ;
EndPaint (hwnd, &ps) ;
return 0 ;
case WM_QUERYOPEN:
return 0 ;
case WM_DESTROY:
KillTimer (hwnd, ID_TIMER) ;
PostQuitMessage (0) ;
return 0 ;
}
return DefWindowProc (hwnd, message, wParam, lParam) ;
}
GRAFMENU.C
CD-ROM Disc Path: \SAMPCODE\PROGWIN\CHAP09\GRAFMENU.C
/*----------------------------------------------
GRAFMENU.C -- Demonstrates Bitmap Menu Items
(c) Charles Petzold, 1990
----------------------------------------------*/
#include <windows.h>
#include <string.h>
#include "grafmenu.h"
long FAR PASCAL WndProc (HWND, WORD, WORD, LONG) ;
HBITMAP StretchBitmap (HBITMAP) ;
HBITMAP GetBitmapFont (int) ;
char szAppName [] = "GrafMenu" ;
int PASCAL WinMain (HANDLE hInstance, HANDLE hPrevInstance,
LPSTR lpszCmdLine, int nCmdShow)
{
HBITMAP hBitmapHelp, hBitmapFile, hBitmapEdit,
hBitmapFont, hBitmapPopFont [3] ;
HMENU hMenu, hMenuPopup ;
HWND hwnd ;
int i ;
MSG msg ;
WNDCLASS wndclass ;
if (!hPrevInstance)
{
wndclass.style = CS_HREDRAW | CS_VREDRAW ;
wndclass.lpfnWndProc = WndProc ;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hInstance = hInstance ;
wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = GetStockObject (WHITE_BRUSH) ;
wndclass.lpszMenuName = NULL ;
wndclass.lpszClassName = szAppName ;
RegisterClass (&wndclass) ;
}
hMenu = CreateMenu () ;
hMenuPopup = LoadMenu (hInstance, "MenuFile") ;
hBitmapFile = StretchBitmap (LoadBitmap (hInstance, "BitmapFile")) ;
AppendMenu (hMenu, MF_BITMAP | MF_POPUP, hMenuPopup,
(LPSTR) (LONG) hBitmapFile);
hMenuPopup = LoadMenu (hInstance, "MenuEdit") ;
hBitmapEdit = StretchBitmap (LoadBitmap (hInstance, "BitmapEdit")) ;
AppendMenu (hMenu, MF_BITMAP | MF_POPUP, hMenuPopup,
(LPSTR) (LONG) hBitmapEdit);
hMenuPopup = CreateMenu () ;
for (i = 0 ; i < 3 ; i++)
{
hBitmapPopFont [i] = GetBitmapFont (i) ;
AppendMenu (hMenuPopup, MF_BITMAP, IDM_COUR + i,
(LPSTR) (LONG) hBitmapPopFont [i]) ;
}
hBitmapFont = StretchBitmap (LoadBitmap (hInstance, "BitmapFont")) ;
AppendMenu (hMenu, MF_BITMAP | MF_POPUP, hMenuPopup,
(LPSTR) (LONG) hBitmapFont);
hwnd = CreateWindow (szAppName, "Bitmap Menu Demonstration",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, hMenu, hInstance, NULL) ;
hMenu = GetSystemMenu (hwnd, FALSE);
hBitmapHelp = StretchBitmap (LoadBitmap (hInstance, "BitmapHelp")) ;
AppendMenu (hMenu, MF_SEPARATOR, NULL, NULL) ;
AppendMenu (hMenu, MF_BITMAP, IDM_HELP, (LPSTR) (LONG) hBitmapHelp) ;
ShowWindow (hwnd, nCmdShow) ;
UpdateWindow (hwnd) ;
while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
DeleteObject (hBitmapHelp) ;
DeleteObject (hBitmapEdit) ;
DeleteObject (hBitmapFile) ;
DeleteObject (hBitmapFont) ;
for (i = 0 ; i < 3 ; i++)
DeleteObject (hBitmapPopFont [i]) ;
return msg.wParam ;
}
HBITMAP StretchBitmap (HBITMAP hBitmap1)
{
BITMAP bm1, bm2 ;
HBITMAP hBitmap2 ;
HDC hdc, hdcMem1, hdcMem2 ;
TEXTMETRIC tm ;
hdc = CreateIC ("DISPLAY", NULL, NULL, NULL) ;
GetTextMetrics (hdc, &tm) ;
hdcMem1 = CreateCompatibleDC (hdc) ;
hdcMem2 = CreateCompatibleDC (hdc) ;
DeleteDC (hdc) ;
GetObject (hBitmap1, sizeof (BITMAP), (LPSTR) &bm1) ;
bm2 = bm1 ;
bm2.bmWidth = (tm.tmAveCharWidth * bm2.bmWidth) / 4 ;
bm2.bmHeight = (tm.tmHeight * bm2.bmHeight) / 8 ;
bm2.bmWidthBytes = ((bm2.bmWidth + 15) / 16) * 2 ;
hBitmap2 = CreateBitmapIndirect (&bm2) ;
SelectObject (hdcMem1, hBitmap1) ;
SelectObject (hdcMem2, hBitmap2) ;
StretchBlt (hdcMem2, 0, 0, bm2.bmWidth, bm2.bmHeight,
hdcMem1, 0, 0, bm1.bmWidth, bm1.bmHeight, SRCCOPY) ;
DeleteDC (hdcMem1) ;
DeleteDC (hdcMem2) ;
DeleteObject (hBitmap1) ;
return hBitmap2 ;
}
HBITMAP GetBitmapFont (int i)
{
static struct
{
BYTE lfPitchAndFamily ;
BYTE lfFaceName [LF_FACESIZE] ;
char *szMenuText ;
}
lfSet [3] =
{
FIXED_PITCH | FF_MODERN, "Courier", "Courier",
VARIABLE_PITCH | FF_SWISS, "Helvetica", "Helvetica",
VARIABLE_PITCH | FF_ROMAN, "Tms Rmn", "Times Roman"
} ;
DWORD dwSize ;
HBITMAP hBitmap ;
HDC hdc, hdcMem ;
HFONT hFont ;
LOGFONT lf ;
hFont = GetStockObject (SYSTEM_FONT) ;
GetObject (hFont, sizeof (LOGFONT), (LPSTR) &lf) ;
lf.lfHeight *= 2 ;
lf.lfWidth *= 2 ;
lf.lfPitchAndFamily = lfSet[i].lfPitchAndFamily ;
strcpy (lf.lfFaceName, lfSet[i].lfFaceName) ;
hdc = CreateIC ("DISPLAY", NULL, NULL, NULL) ;
hdcMem = CreateCompatibleDC (hdc) ;
SelectObject (hdcMem, CreateFontIndirect (&lf)) ;
dwSize = GetTextExtent (hdcMem, lfSet[i].szMenuText,
strlen (lfSet[i].szMenuText)) ;
hBitmap = CreateBitmap (LOWORD (dwSize)-1, HIWORD (dwSize), 1, 1, NULL)
SelectObject (hdcMem, hBitmap) ;
TextOut (hdcMem, 0, 0, lfSet[i].szMenuText,
strlen (lfSet[i].szMenuText)) ;
DeleteObject (SelectObject (hdcMem, hFont)) ;
DeleteDC (hdcMem) ;
DeleteDC (hdc) ;
return hBitmap ;
}
long FAR PASCAL WndProc (HWND hwnd, WORD message, WORD wParam, LONG lParam)
{
HMENU hMenu ;
static short nCurrentFont = IDM_COUR ;
switch (message)
{
case WM_CREATE:
CheckMenuItem (GetMenu (hwnd), nCurrentFont, MF_CHECKED) ;
return 0 ;
case WM_SYSCOMMAND:
switch (wParam)
{
case IDM_HELP:
MessageBox (hwnd, "Help not yet implemented.",
szAppName, MB_OK | MB_ICONEXCLAMATION) ;
return 0 ;
}
break ;
case WM_COMMAND:
switch (wParam)
{
case IDM_NEW:
case IDM_OPEN:
case IDM_SAVE:
case IDM_SAVEAS:
case IDM_UNDO:
case IDM_CUT:
case IDM_COPY:
case IDM_PASTE:
case IDM_CLEAR:
MessageBeep (0) ;
return 0 ;
case IDM_COUR:
case IDM_HELV:
case IDM_TMSRMN:
hMenu = GetMenu (hwnd) ;
CheckMenuItem (hMenu, nCurrentFont, MF_UNCHECKED) ;
nCurrentFont = wParam ;
CheckMenuItem (hMenu, nCurrentFont, MF_CHECKED) ;
return 0 ;
}
break ;
case WM_DESTROY:
PostQuitMessage (0) ;
return 0 ;
}
return DefWindowProc (hwnd, message, wParam, lParam) ;
}
HEAD.C
CD-ROM Disc Path: \SAMPCODE\PROGWIN\CHAP06\HEAD.C
/*---------------------------------------------
HEAD.C -- Displays beginning (head) of file
(c) Charles Petzold, 1990
---------------------------------------------*/
#include <windows.h>
#include <io.h>
#include <string.h>
#include <direct.h>
#define MAXPATH 100
#define MAXREAD 2048
long FAR PASCAL WndProc (HWND, WORD, WORD, LONG) ;
long FAR PASCAL ListProc (HWND, WORD, WORD, LONG) ;
char sReadBuffer [MAXREAD] ;
FARPROC lpfnOldList ;
int PASCAL WinMain (HANDLE hInstance, HANDLE hPrevInstance,
LPSTR lpszCmdLine, int nCmdShow)
{
static char szAppName [] = "Head" ;
HWND hwnd ;
MSG msg ;
WNDCLASS wndclass ;
if (!hPrevInstance)
{
wndclass.style = CS_HREDRAW | CS_VREDRAW ;
wndclass.lpfnWndProc = WndProc ;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hInstance = hInstance ;
wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = COLOR_WINDOW + 1 ;
wndclass.lpszMenuName = NULL ;
wndclass.lpszClassName = szAppName ;
RegisterClass (&wndclass) ;
}
hwnd = CreateWindow (szAppName, "File Head",
WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL) ;
ShowWindow (hwnd, nCmdShow) ;
UpdateWindow (hwnd) ;
while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
return msg.wParam ;
}
long FAR PASCAL WndProc (HWND hwnd, WORD message, WORD wParam, LONG lParam)
{
static BOOL bValidFile ;
static char szFile [16] ;
static HWND hwndList, hwndText ;
static OFSTRUCT ofs ;
static RECT rect ;
char szBuffer [MAXPATH + 1] ;
HDC hdc ;
int iHandle, i, iCount ;
PAINTSTRUCT ps ;
TEXTMETRIC tm ;
switch (message)
{
case WM_CREATE:
hdc = GetDC (hwnd) ;
SelectObject (hdc, GetStockObject (SYSTEM_FIXED_FONT)) ;
GetTextMetrics (hdc, &tm) ;
ReleaseDC (hwnd, hdc) ;
rect.left = 20 * tm.tmAveCharWidth ;
rect.top = 3 * tm.tmHeight ;
hwndList = CreateWindow ("listbox", NULL,
WS_CHILDWINDOW | WS_VISIBLE | LBS_STANDARD,
tm.tmAveCharWidth, tm.tmHeight * 3,
tm.tmAveCharWidth * 13 +
GetSystemMetrics (SM_CXVSCROLL),
tm.tmHeight * 10,
hwnd, 1,
GetWindowWord (hwnd, GWW_HINSTANCE), NULL) ;
hwndText = CreateWindow ("static", getcwd (szBuffer, MAXPATH),
WS_CHILDWINDOW | WS_VISIBLE | SS_LEFT,
tm.tmAveCharWidth, tm.tmHeight,
tm.tmAveCharWidth * MAXPATH, tm.tmHeight,
hwnd, 2,
GetWindowWord (hwnd, GWW_HINSTANCE), NULL) ;
lpfnOldList = (FARPROC) GetWindowLong (hwndList, GWL_WNDPROC)
SetWindowLong (hwndList, GWL_WNDPROC,
(LONG) MakeProcInstance ((FARPROC) ListProc,
GetWindowWord (hwnd, GWW_HINSTANCE))) ;
SendMessage (hwndList, LB_DIR, 0x37, (LONG) (LPSTR) "*.*") ;
return 0 ;
case WM_SIZE:
rect.right = LOWORD (lParam) ;
rect.bottom = HIWORD (lParam) ;
return 0 ;
case WM_SETFOCUS:
SetFocus (hwndList) ;
return 0 ;
case WM_COMMAND:
if (wParam == 1 && HIWORD (lParam) == LBN_DBLCLK)
{
if (LB_ERR == (i = (WORD) SendMessage (hwndList,
LB_GETCURSEL, 0, 0L)))
break ;
SendMessage (hwndList, LB_GETTEXT, i,
(LONG) (char far *) szBuffer) ;
if (-1 != OpenFile (szBuffer, &ofs, OF_EXIST | OF_READ))
{
bValidFile = TRUE ;
strcpy (szFile, szBuffer) ;
getcwd (szBuffer, MAXPATH) ;
if (szBuffer [strlen (szBuffer) - 1] != '\\')
strcat (szBuffer, "\\") ;
SetWindowText (hwndText, strcat (szBuffer, szFile))
}
else
{
bValidFile = FALSE ;
szBuffer [strlen (szBuffer) - 1] = '\0' ;
chdir (szBuffer + 1) ;
getcwd (szBuffer, MAXPATH) ;
SetWindowText (hwndText, szBuffer) ;
SendMessage (hwndList, LB_RESETCONTENT, 0, 0L) ;
SendMessage (hwndList, LB_DIR, 0x37,
(LONG) (LPSTR) "*.*") ;
}
InvalidateRect (hwnd, NULL, TRUE) ;
}
return 0 ;
case WM_PAINT:
hdc = BeginPaint (hwnd, &ps) ;
SelectObject (hdc, GetStockObject (SYSTEM_FIXED_FONT)) ;
SetTextColor (hdc, GetSysColor (COLOR_WINDOWTEXT)) ;
SetBkColor (hdc, GetSysColor (COLOR_WINDOW)) ;
if (bValidFile && -1 != (iHandle =
OpenFile (szFile, &ofs, OF_REOPEN | OF_READ)))
{
i = read (iHandle, sReadBuffer, MAXREAD) ;
close (iHandle) ;
DrawText (hdc, sReadBuffer, i, &rect, DT_WORDBREAK |
DT_EXPANDTABS | DT_NOCLIP | DT_NOPREFIX) ;
}
else
bValidFile = FALSE ;
EndPaint (hwnd, &ps) ;
return 0 ;
case WM_DESTROY:
PostQuitMessage (0) ;
return 0 ;
}
return DefWindowProc (hwnd, message, wParam, lParam) ;
}
long FAR PASCAL ListProc (HWND hwnd, WORD message, WORD wParam, LONG lParam)
{
if (message == WM_KEYDOWN && wParam == VK_RETURN)
SendMessage (GetParent (hwnd), WM_COMMAND, 1,
MAKELONG (hwnd, LBN_DBLCLK)) ;
return CallWindowProc (lpfnOldList, hwnd, message, wParam, lParam) ;
}
HELLOWIN.C
CD-ROM Disc Path: \SAMPCODE\PROGWIN\CHAP01\HELLOWIN.C
/*--------------------------------------------------------
HELLOWIN.C -- Displays "Hello, Windows" in client area
(c) Charles Petzold, 1990
--------------------------------------------------------*/
#include <windows.h>
long FAR PASCAL WndProc (HWND, WORD, WORD, LONG) ;
int PASCAL WinMain (HANDLE hInstance, HANDLE hPrevInstance,
LPSTR lpszCmdParam, int nCmdShow)
{
static char szAppName[] = "HelloWin" ;
HWND hwnd ;
MSG msg ;
WNDCLASS wndclass ;
if (!hPrevInstance)
{
wndclass.style = CS_HREDRAW | CS_VREDRAW ;
wndclass.lpfnWndProc = WndProc ;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hInstance = hInstance ;
wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = GetStockObject (WHITE_BRUSH) ;
wndclass.lpszMenuName = NULL ;
wndclass.lpszClassName = szAppName ;
RegisterClass (&wndclass) ;
}
hwnd = CreateWindow (szAppName, // window class name
"The Hello Program", // window caption
WS_OVERLAPPEDWINDOW, // window style
CW_USEDEFAULT, // initial x position
CW_USEDEFAULT, // initial y position
CW_USEDEFAULT, // initial x size
CW_USEDEFAULT, // initial y size
NULL, // parent window handle
NULL, // window menu handle
hInstance, // program instance handle
NULL) ; // creation parameters
ShowWindow (hwnd, nCmdShow) ;
UpdateWindow (hwnd) ;
while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
return msg.wParam ;
}
long FAR PASCAL WndProc (HWND hwnd, WORD message, WORD wParam, LONG lParam)
{
HDC hdc ;
PAINTSTRUCT ps ;
RECT rect ;
switch (message)
{
case WM_PAINT:
hdc = BeginPaint (hwnd, &ps) ;
GetClientRect (hwnd, &rect) ;
DrawText (hdc, "Hello, Windows!", -1, &rect,
DT_SINGLELINE | DT_CENTER | DT_VCENTER) ;
EndPaint (hwnd, &ps) ;
return 0 ;
case WM_DESTROY:
PostQuitMessage (0) ;
return 0 ;
}
return DefWindowProc (hwnd, message, wParam, lParam) ;
}
HEXCALC.C
CD-ROM Disc Path: \SAMPCODE\PROGWIN\CHAP10\HEXCALC.C
/*----------------------------------------
HEXCALC.C -- Hexadecimal Calculator
(c) Charles Petzold, 1990
----------------------------------------*/
#include <windows.h>
#include <limits.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
long FAR PASCAL WndProc (HWND, WORD, WORD, LONG) ;
int PASCAL WinMain (HANDLE hInstance, HANDLE hPrevInstance,
LPSTR lpszCmdLine, int nCmdShow)
{
static char szAppName [] = "HexCalc" ;
HWND hwnd ;
MSG msg;
WNDCLASS wndclass ;
if (!hPrevInstance)
{
wndclass.style = CS_HREDRAW | CS_VREDRAW;
wndclass.lpfnWndProc = WndProc ;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = DLGWINDOWEXTRA ;
wndclass.hInstance = hInstance ;
wndclass.hIcon = LoadIcon (hInstance, szAppName) ;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = COLOR_WINDOW + 1 ;
wndclass.lpszMenuName = NULL ;
wndclass.lpszClassName = szAppName ;
RegisterClass (&wndclass) ;
}
hwnd = CreateDialog (hInstance, szAppName, 0, NULL) ;
ShowWindow (hwnd, nCmdShow) ;
while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
return msg.wParam ;
}
void ShowNumber (HWND hwnd, DWORD dwNumber)
{
char szBuffer [20] ;
SetDlgItemText (hwnd, VK_ESCAPE, strupr (ltoa (dwNumber, szBuffer, 16)))
}
DWORD CalcIt (DWORD dwFirstNum, short nOperation, DWORD dwNum)
{
switch (nOperation)
{
case '=' : return dwNum ;
case '+' : return dwFirstNum + dwNum ;
case '-' : return dwFirstNum - dwNum ;
case '*' : return dwFirstNum * dwNum ;
case '&' : return dwFirstNum & dwNum ;
case '|' : return dwFirstNum | dwNum ;
case '^' : return dwFirstNum ^ dwNum ;
case '<' : return dwFirstNum << dwNum ;
case '>' : return dwFirstNum >> dwNum ;
case '/' : return dwNum ? dwFirstNum / dwNum : ULONG_MAX ;
case '%' : return dwNum ? dwFirstNum % dwNum : ULONG_MAX ;
default : return 0L ;
}
}
long FAR PASCAL WndProc (HWND hwnd, WORD message, WORD wParam, LONG lParam)
{
static BOOL bNewNumber = TRUE ;
static DWORD dwNumber, dwFirstNum ;
static short nOperation = '=' ;
HWND hButton ;
switch (message)
{
case WM_KEYDOWN: // left arrow --> backspace
if (wParam != VK_LEFT)
break ;
wParam = VK_BACK ;
// fall through
case WM_CHAR:
if ((wParam = toupper (wParam)) == VK_RETURN)
wParam = '=' ;
if (hButton = GetDlgItem (hwnd, wParam))
{
SendMessage (hButton, BM_SETSTATE, 1, 0L) ;
SendMessage (hButton, BM_SETSTATE, 0, 0L) ;
}
else
{
MessageBeep (0) ;
break ;
}
// fall through
case WM_COMMAND:
SetFocus (hwnd) ;
if (wParam == VK_BACK) // backspace
ShowNumber (hwnd, dwNumber /= 16) ;
else if (wParam == VK_ESCAPE) // escape
ShowNumber (hwnd, dwNumber = 0L) ;
else if (isxdigit (wParam)) // hex digit
{
if (bNewNumber)
{
dwFirstNum = dwNumber ;
dwNumber = 0L ;
}
bNewNumber = FALSE ;
if (dwNumber <= ULONG_MAX >> 4)
ShowNumber (hwnd, dwNumber = 16 * dwNumber + wParam
(isdigit (wParam) ? '0' : 'A' - 10)) ;
else
MessageBeep (0) ;
}
else // operation
{
if (!bNewNumber)
ShowNumber (hwnd, dwNumber =
CalcIt (dwFirstNum, nOperation, dwNumber)) ;
bNewNumber = TRUE ;
nOperation = wParam ;
}
return 0 ;
case WM_DESTROY:
PostQuitMessage (0) ;
return 0 ;
}
return DefWindowProc (hwnd, message, wParam, lParam) ;
}
JUSTIFY.C
CD-ROM Disc Path: \SAMPCODE\PROGWIN\CHAP14\JUSTIFY.C
/*----------------------------------------
JUSTIFY.C -- Justified Type Program
(c) Charles Petzold, 1990
----------------------------------------*/
#include <windows.h>
#include <string.h>
#include "justify.h"
typedef struct
{
short nNumFaces ;
char szFaceNames [MAX_FACES] [LF_FACESIZE] ;
}
ENUMFACE ;
typedef struct
{
short nNumSizes ;
short xLogPixPerInch ;
short yLogPixPerInch ;
LOGFONT lf [MAX_SIZES] ;
TEXTMETRIC tm [MAX_SIZES] ;
}
ENUMSIZE ;
long FAR PASCAL WndProc (HWND, WORD, WORD, LONG) ;
int FAR PASCAL EnumAllFaces (LPLOGFONT, LPTEXTMETRIC, short, ENUMFACE FAR *)
int FAR PASCAL EnumAllSizes (LPLOGFONT, LPTEXTMETRIC, short, ENUMSIZE FAR *)
int PASCAL WinMain (HANDLE hInstance, HANDLE hPrevInstance,
LPSTR lpszCmdLine, int nCmdShow)
{
static char szAppName[] = "Justify" ;
HWND hwnd ;
MSG msg ;
WNDCLASS wndclass ;
if (!hPrevInstance)
{
wndclass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC ;
wndclass.lpfnWndProc = WndProc ;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hInstance = hInstance ;
wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = GetStockObject (WHITE_BRUSH) ;
wndclass.lpszMenuName = szAppName ;
wndclass.lpszClassName = szAppName ;
RegisterClass (&wndclass) ;
}
hwnd = CreateWindow (szAppName, "Justified Type",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL) ;
ShowWindow (hwnd, nCmdShow) ;
UpdateWindow (hwnd) ;
while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
return msg.wParam ;
}
int FAR PASCAL EnumAllFaces (LPLOGFONT lplf, LPTEXTMETRIC lptm,
short nFontType, ENUMFACE FAR *lpef)
{
if (nFontType & RASTER_FONTTYPE)
{
lstrcpy (lpef->szFaceNames[lpef->nNumFaces], lplf->lfFaceName) ;
if (++lpef->nNumFaces == MAX_FACES)
return 0 ;
}
return 1 ;
}
int FAR PASCAL EnumAllSizes (LPLOGFONT lplf, LPTEXTMETRIC lptm,
short nFontType, ENUMSIZE FAR *lpes)
{
if (lpes->xLogPixPerInch == lptm->tmDigitizedAspectX &&
lpes->yLogPixPerInch == lptm->tmDigitizedAspectY)
{
lpes->lf [lpes->nNumSizes] = *lplf ;
lpes->tm [lpes->nNumSizes] = *lptm ;
if (++lpes->nNumSizes == MAX_SIZES)
return 0 ;
}
return 1 ;
}
short MakeSizeMenu (HWND hwnd, FARPROC lpfnEnumAllSizes,
ENUMSIZE *pes, char *szFaceName)
{
static LOGFONT lfBlank ;
char szBuffer[20] ;
HDC hdc ;
HMENU hPopup ;
short i ;
hdc = GetDC (hwnd) ;
hPopup = GetSubMenu (GetMenu (hwnd), SIZE_MENU) ;
pes->nNumSizes = 0 ;
EnumFonts (hdc, szFaceName, lpfnEnumAllSizes, (LPSTR) pes) ;
ReleaseDC (hwnd, hdc) ;
while (GetMenuItemCount (hPopup) > 0)
DeleteMenu (hPopup, 0, MF_BYPOSITION) ;
if (pes->nNumSizes)
for (i = 0 ; i < pes->nNumSizes ; i++)
{
wsprintf (szBuffer, "%i %2d / %2d", i + 1,
(pes->tm[i].tmHeight - pes->tm[i].tmInternalLeading + 10)
/ 20,
(pes->tm[i].tmHeight + 10) / 20) ;
AppendMenu (hPopup, 0, IDM_ISIZE + i, szBuffer) ;
}
else /* no fonts found that match aspect ratio of display */
{
pes->lf[0] = lfBlank ;
strcpy (pes->lf[0].lfFaceName, szFaceName) ;
AppendMenu (hPopup, 0, IDM_ISIZE, "Default") ;
}
CheckMenuItem (hPopup, IDM_ISIZE, MF_CHECKED) ;
return 0 ;
}
void DrawRuler (HDC hdc, POINT ptClient)
{
static short nRuleSize [16] = { 360, 72, 144, 72, 216, 72, 144, 72,
288, 72, 144, 72, 216, 72, 144, 72 } ;
short i, j ;
MoveTo (hdc, 0, -360) ;
LineTo (hdc, ptClient.x, -360) ;
MoveTo (hdc, -360, 0) ;
LineTo (hdc, -360, ptClient.y) ;
for (i = 0, j = 0 ; i <= ptClient.x ; i += 1440 / 16, j++)
{
MoveTo (hdc, i, -360) ;
LineTo (hdc, i, -360 - nRuleSize [j % 16]) ;
}
for (i = 0, j = 0 ; i <= ptClient.y ; i += 1440 / 16, j++)
{
MoveTo (hdc, -360, i) ;
LineTo (hdc, -360 - nRuleSize [j % 16], i) ;
}
}
void Justify (HDC hdc, HANDLE hResource, POINT ptClient, short nCurAlign)
{
DWORD dwExtent ;
LPSTR lpText, lpBegin, lpEnd ;
short i, xStart, yStart, nBreakCount ;
lpText = LockResource (hResource) ;
yStart = 0 ;
do // for each text line
{
nBreakCount = 0 ;
while (*lpText == ' ') // skip over leading blanks
lpText++ ;
lpBegin = lpText ;
do // until the line is known
{
lpEnd = lpText ;
while (*lpText != '\0' && *lpText++ != ' ') ;
if (*lpText == '\0')
break ;
// for each space, calculate extents
nBreakCount++ ;
SetTextJustification (hdc, 0, 0) ;
dwExtent = GetTextExtent (hdc, lpBegin, lpText - lpBegin - 1)
}
while (LOWORD (dwExtent) < ptClient.x) ;
nBreakCount-- ;
while (*(lpEnd - 1) == ' ') // eliminate trailing blanks
{
lpEnd-- ;
nBreakCount-- ;
}
if (*lpText == '\0' || nBreakCount <= 0)
lpEnd = lpText ;
SetTextJustification (hdc, 0, 0) ;
dwExtent = GetTextExtent (hdc, lpBegin, lpEnd - lpBegin) ;
if (nCurAlign == IDM_LEFT) // use alignment for xStart
xStart = 0 ;
else if (nCurAlign == IDM_RIGHT)
xStart = ptClient.x - LOWORD (dwExtent) ;
else if (nCurAlign == IDM_CENTER)
xStart = (ptClient.x - LOWORD (dwExtent)) / 2 ;
else
{
if (*lpText != '\0' && nBreakCount > 0)
SetTextJustification (hdc, ptClient.x - LOWORD (dwExtent)
nBreakCount) ;
xStart = 0 ;
}
TextOut (hdc, xStart, yStart, lpBegin, lpEnd - lpBegin) ;
yStart += HIWORD (dwExtent) ;
lpText = lpEnd ;
}
while (*lpText && yStart < ptClient.y) ;
GlobalUnlock (hResource) ;
}
long FAR PASCAL WndProc (HWND hwnd, WORD message, WORD wParam, LONG lParam)
{
static ENUMFACE ef ;
static ENUMSIZE es ;
static FARPROC lpfnEnumAllFaces, lpfnEnumAllSizes ;
static HANDLE hResource ;
static POINT ptClient ;
static short nCurSize, nCurFace, nCurAttr, nCurAlign = IDM_LEFT ;
HANDLE hInstance ;
HDC hdc ;
HFONT hFont ;
HMENU hMenu, hPopup ;
PAINTSTRUCT ps ;
short i ;
switch (message)
{
case WM_CREATE:
hdc = GetDC (hwnd) ;
es.xLogPixPerInch = GetDeviceCaps (hdc, LOGPIXELSX) ;
es.yLogPixPerInch = GetDeviceCaps (hdc, LOGPIXELSY) ;
// Set Map Mode
SetMapMode (hdc, MM_ANISOTROPIC) ;
SetWindowExt (hdc, 1440, 1440) ;
SetViewportExt (hdc, es.xLogPixPerInch, es.yLogPixPerInch) ;
SetWindowOrg (hdc, -720, -720) ;
// MakeProcInstance for 2 routines
hInstance = ((LPCREATESTRUCT) lParam)-> hInstance ;
lpfnEnumAllFaces = MakeProcInstance (EnumAllFaces, hInstance)
lpfnEnumAllSizes = MakeProcInstance (EnumAllSizes, hInstance)
// Enumerate the Font Faces
EnumFonts (hdc, NULL, lpfnEnumAllFaces, (LPSTR) &ef) ;
ReleaseDC (hwnd, hdc) ;
// Initialize the Menus
hMenu = GetMenu (hwnd) ;
hPopup = CreateMenu () ;
for (i = 0 ; i < ef.nNumFaces ; i++)
AppendMenu (hPopup, 0, IDM_IFACE + i, ef.szFaceNames[i])
ModifyMenu (hMenu, IDM_FACE, MF_POPUP, hPopup, "&FaceName") ;
CheckMenuItem (hMenu, IDM_IFACE, MF_CHECKED) ;
nCurSize = MakeSizeMenu (hwnd, lpfnEnumAllSizes, &es,
ef.szFaceNames [nCurFace]) ;
// Load the Text Resource
hResource = LoadResource (hInstance,
FindResource (hInstance, "Ismael", "TEXT")) ;
return 0 ;
case WM_SIZE:
hdc = GetDC (hwnd) ;
ptClient = MAKEPOINT (lParam) ;
DPtoLP (hdc, &ptClient, 1) ;
ptClient.x -= 360 ;
ReleaseDC (hwnd, hdc) ;
return 0 ;
case WM_COMMAND:
hMenu = GetMenu (hwnd) ;
if (wParam >= IDM_IFACE && wParam < IDM_IFACE + MAX_FACES)
{
CheckMenuItem (hMenu, nCurFace + IDM_IFACE, MF_UNCHECKED)
CheckMenuItem (hMenu, wParam, MF_CHECKED) ;
nCurFace = wParam - IDM_IFACE ;
nCurSize = MakeSizeMenu (hwnd, lpfnEnumAllSizes, &es,
ef.szFaceNames [nCurFace]) ;
}
else if (wParam >= IDM_ISIZE && wParam < IDM_ISIZE + MAX_SIZES
{
CheckMenuItem (hMenu, nCurSize + IDM_ISIZE, MF_UNCHECKED)
CheckMenuItem (hMenu, wParam, MF_CHECKED) ;
nCurSize = wParam - IDM_ISIZE ;
}
else switch (wParam)
{
case IDM_BOLD:
case IDM_ITALIC:
case IDM_STRIKE:
case IDM_UNDER:
CheckMenuItem (hMenu, wParam, MF_CHECKED &
GetMenuState (hMenu, wParam, MF_BYCOMMAND) ?
MF_UNCHECKED : MF_CHECKED) ;
nCurAttr ^= wParam ;
break ;
case IDM_NORM:
nCurAttr = 0 ;
CheckMenuItem (hMenu, IDM_BOLD, MF_UNCHECKED) ;
CheckMenuItem (hMenu, IDM_ITALIC, MF_UNCHECKED) ;
CheckMenuItem (hMenu, IDM_STRIKE, MF_UNCHECKED) ;
CheckMenuItem (hMenu, IDM_UNDER, MF_UNCHECKED) ;
break ;
case IDM_LEFT:
case IDM_RIGHT:
case IDM_CENTER:
case IDM_JUST:
CheckMenuItem (hMenu, nCurAlign, MF_UNCHECKED) ;
nCurAlign = wParam ;
CheckMenuItem (hMenu, nCurAlign, MF_CHECKED) ;
break ;
}
InvalidateRect (hwnd, NULL, TRUE) ;
return 0 ;
case WM_PAINT:
hdc = BeginPaint (hwnd, &ps) ;
es.lf[nCurSize].lfWeight = nCurAttr & IDM_BOLD ? 700 : 400
es.lf[nCurSize].lfItalic = (BYTE) (nCurAttr & IDM_ITALIC) ;
es.lf[nCurSize].lfUnderline = (BYTE) (nCurAttr & IDM_UNDER) ;
es.lf[nCurSize].lfStrikeOut = (BYTE) (nCurAttr & IDM_STRIKE) ;
hFont = CreateFontIndirect (&es.lf[nCurSize]) ;
hFont = SelectObject (hdc, hFont) ;
DrawRuler (hdc, ptClient) ;
Justify (hdc, hResource, ptClient, nCurAlign) ;
DeleteObject (SelectObject (hdc, hFont)) ;
EndPaint (hwnd, &ps) ;
return 0 ;
case WM_DESTROY:
FreeResource (hResource) ;
PostQuitMessage (0) ;
return 0 ;
}
return DefWindowProc (hwnd, message, wParam, lParam) ;
}
KEYLOOK.C
CD-ROM Disc Path: \SAMPCODE\PROGWIN\CHAP03\KEYLOOK.C
/*-------------------------------------------------------
KEYLOOK.C -- Displays Keyboard and Character Messages
(c) Charles Petzold, 1990
-------------------------------------------------------*/
#include <windows.h>
#include <stdio.h>
long FAR PASCAL WndProc (HWND, WORD, WORD, LONG) ;
RECT rect ;
short cxChar, cyChar ;
int PASCAL WinMain (HANDLE hInstance, HANDLE hPrevInstance,
LPSTR lpszCmdLine, int nCmdShow)
{
static char szAppName[] = "KeyLook" ;
HWND hwnd ;
MSG msg ;
WNDCLASS wndclass ;
if (!hPrevInstance)
{
wndclass.style = CS_HREDRAW | CS_VREDRAW ;
wndclass.lpfnWndProc = WndProc ;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hInstance = hInstance ;
wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
wndclass.lpszMenuName = NULL ;
wndclass.lpszClassName = szAppName ;
RegisterClass (&wndclass) ;
}
hwnd = CreateWindow (szAppName, "Keyboard Message Looker",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL) ;
ShowWindow (hwnd, nCmdShow) ;
UpdateWindow (hwnd) ;
while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
return msg.wParam ;
}
void ShowKey (HWND hwnd, int iType, char *szMessage, WORD wParam, LONG lParam
{
static char *szFormat[2] = { "%-14s %3d %c %6u %4d %3s %3s %4s %4s",
"%-14s %3d %c %6u %4d %3s %3s %4s %4s" }
char szBuffer[80] ;
HDC hdc ;
ScrollWindow (hwnd, 0, -cyChar, &rect, &rect) ;
hdc = GetDC (hwnd) ;
SelectObject (hdc, GetStockObject (SYSTEM_FIXED_FONT)) ;
TextOut (hdc, cxChar, rect.bottom - cyChar, szBuffer,
wsprintf (szBuffer, szFormat [iType],
(LPSTR) szMessage, wParam,
(BYTE) (iType ? wParam : ' '),
LOWORD (lParam),
HIWORD (lParam) & 0xFF,
(LPSTR) (0x01000000 & lParam ? "Yes" : "No"),
(LPSTR) (0x20000000 & lParam ? "Yes" : "No"),
(LPSTR) (0x40000000 & lParam ? "Down" : "Up"),
(LPSTR) (0x80000000 & lParam ? "Up" : "Down"))) ;
ReleaseDC (hwnd, hdc) ;
ValidateRect (hwnd, NULL) ;
}
long FAR PASCAL WndProc (HWND hwnd, WORD message, WORD wParam, LONG lParam)
{
static char szTop[] =
"Message Key Char Repeat Scan Ext ALT Prev Tran";
static char szUnd[]=
"_______ ___ ____ ______ ____ ___ ___ ____ ____";
HDC hdc ;
PAINTSTRUCT ps ;
TEXTMETRIC tm ;
switch (message)
{
case WM_CREATE:
hdc = GetDC (hwnd) ;
SelectObject (hdc, GetStockObject (SYSTEM_FIXED_FONT)) ;
GetTextMetrics (hdc, &tm) ;
cxChar = tm.tmAveCharWidth ;
cyChar = tm.tmHeight ;
ReleaseDC (hwnd, hdc) ;
rect.top = 3 * cyChar / 2 ;
return 0 ;
case WM_SIZE:
rect.right = LOWORD (lParam) ;
rect.bottom = HIWORD (lParam) ;
UpdateWindow (hwnd) ;
return 0 ;
case WM_PAINT:
InvalidateRect (hwnd, NULL, TRUE) ;
hdc = BeginPaint (hwnd, &ps) ;
SelectObject (hdc, GetStockObject (SYSTEM_FIXED_FONT)) ;
SetBkMode (hdc, TRANSPARENT) ;
TextOut (hdc, cxChar, cyChar / 2, szTop, (sizeof szTop) - 1) ;
TextOut (hdc, cxChar, cyChar / 2, szUnd, (sizeof szUnd) - 1) ;
EndPaint (hwnd, &ps) ;
return 0 ;
case WM_KEYDOWN:
ShowKey (hwnd, 0, "WM_KEYDOWN", wParam, lParam) ;
return 0 ;
case WM_KEYUP:
ShowKey (hwnd, 0, "WM_KEYUP", wParam, lParam) ;
return 0 ;
case WM_CHAR:
ShowKey (hwnd, 1, "WM_CHAR", wParam, lParam) ;
return 0 ;
case WM_DEADCHAR:
ShowKey (hwnd, 1, "WM_DEADCHAR", wParam, lParam) ;
return 0 ;
case WM_SYSKEYDOWN:
ShowKey (hwnd, 0, "WM_SYSKEYDOWN", wParam, lParam) ;
break ; // ie, call DefWindowProc
case WM_SYSKEYUP:
ShowKey (hwnd, 0, "WM_SYSKEYUP", wParam, lParam) ;
break ; // ie, call DefWindowProc
case WM_SYSCHAR:
ShowKey (hwnd, 1, "WM_SYSCHAR", wParam, lParam) ;
break ; // ie, call DefWindowProc
case WM_SYSDEADCHAR:
ShowKey (hwnd, 1, "WM_SYSDEADCHAR", wParam, lParam) ;
break ; // ie, call DefWindowProc
case WM_DESTROY:
PostQuitMessage (0) ;
return 0 ;
}
return DefWindowProc (hwnd, message, wParam, lParam) ;
}
LINEDDA.C
CD-ROM Disc Path: \SAMPCODE\PROGWIN\CHAP12\LINEDDA.C
/*----------------------------------------
LINEDDA.C -- LineDDA Demonstration
(c) Charles Petzold, 1990
----------------------------------------*/
#include <windows.h>
long FAR PASCAL WndProc (HWND, WORD, WORD, LONG) ;
void FAR PASCAL LineProc (short, short, LPSTR) ;
HANDLE hInst ;
int PASCAL WinMain (HANDLE hInstance, HANDLE hPrevInstance,
LPSTR lpszCmdLine, int nCmdShow)
{
static char szAppName[] = "LineDDA" ;
HWND hwnd ;
MSG msg ;
WNDCLASS wndclass ;
if (!hPrevInstance)
{
wndclass.style = CS_HREDRAW | CS_VREDRAW ;
wndclass.lpfnWndProc = WndProc ;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hInstance = hInstance ;
wndclass.hIcon = NULL ;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = GetStockObject (WHITE_BRUSH) ;
wndclass.lpszMenuName = NULL ;
wndclass.lpszClassName = szAppName ;
RegisterClass (&wndclass) ;
}
hInst = hInstance ;
hwnd = CreateWindow (szAppName, "LineDDA Demonstration",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL) ;
ShowWindow (hwnd, nCmdShow) ;
UpdateWindow (hwnd) ;
while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
return msg.wParam ;
}
long FAR PASCAL WndProc (HWND hwnd, WORD message, WORD wParam, LONG lParam)
{
static FARPROC lpfnLineProc ;
static short cxClient, cyClient, xL, xR, yT, yB ;
HDC hdc ;
PAINTSTRUCT ps ;
switch (message)
{
case WM_CREATE:
lpfnLineProc = MakeProcInstance (LineProc, hInst) ;
return 0 ;
case WM_SIZE:
xR = 3 * (xL = (cxClient = LOWORD (lParam)) / 4) ;
yB = 3 * (yT = (cyClient = HIWORD (lParam)) / 4) ;
return 0 ;
case WM_PAINT:
hdc = BeginPaint (hwnd, &ps) ;
LineDDA (xL, yT, xR, yT, lpfnLineProc, (LPSTR) &hdc) ;
LineDDA (xR, yT, xR, yB, lpfnLineProc, (LPSTR) &hdc) ;
LineDDA (xR, yB, xL, yB, lpfnLineProc, (LPSTR) &hdc) ;
LineDDA (xL, yB, xL, yT, lpfnLineProc, (LPSTR) &hdc) ;
LineDDA (0, 0, xL, yT, lpfnLineProc, (LPSTR) &hdc)
LineDDA (cxClient, 0, xR, yT, lpfnLineProc, (LPSTR) &hdc
LineDDA (cxClient, cyClient, xR, yB, lpfnLineProc, (LPSTR) &hd
LineDDA (0, cyClient, xL, yB, lpfnLineProc, (LPSTR) &hdc
EndPaint (hwnd, &ps) ;
return 0 ;
case WM_DESTROY:
PostQuitMessage (0) ;
return 0 ;
}
return DefWindowProc (hwnd, message, wParam, lParam) ;
}
void FAR PASCAL LineProc (short x, short y, LPSTR lpData)
{
static short nCounter = 0 ;
if (nCounter == 2)
Ellipse (* (HDC far *) lpData, x - 2, y - 2, x + 3, y + 3) ;
nCounter = (nCounter + 1) % 4 ;
}
MDIDEMO.C
CD-ROM Disc Path: \SAMPCODE\PROGWIN\CHAP18\MDIDEMO.C
/*--------------------------------------------------------
MDIDEMO.C -- Multiple Document Interface Demonstration
(c) Charles Petzold, 1990
--------------------------------------------------------*/
#include <windows.h>
#include <stdlib.h>
#include "mdidemo.h"
long FAR PASCAL FrameWndProc (HWND, WORD, WORD, LONG) ;
BOOL FAR PASCAL CloseEnumProc (HWND, LONG) ;
long FAR PASCAL HelloWndProc (HWND, WORD, WORD, LONG) ;
long FAR PASCAL RectWndProc (HWND, WORD, WORD, LONG) ;
// structure for storing data unique to each Hello child window
typedef struct
{
short nColor ;
COLORREF clrText ;
}
HELLODATA ;
typedef HELLODATA NEAR *NPHELLODATA ;
// structure for storing data unique to each Rect child window
typedef struct
{
short cxClient ;
short cyClient ;
}
RECTDATA ;
typedef RECTDATA NEAR *NPRECTDATA ;
// global variables
char szFrameClass [] = "MdiFrame" ;
char szHelloClass [] = "MdiHelloChild" ;
char szRectClass [] = "MdiRectChild" ;
HANDLE hInst ;
HMENU hMenuInit, hMenuHello, hMenuRect ;
HMENU hMenuInitWindow, hMenuHelloWindow, hMenuRectWindow ;
int PASCAL WinMain (HANDLE hInstance, HANDLE hPrevInstance,
LPSTR lpszCmdLine, int nCmdShow)
{
HANDLE hAccel ;
HWND hwndFrame, hwndClient ;
MSG msg ;
WNDCLASS wndclass ;
hInst = hInstance ;
if (!hPrevInstance)
{
// Register the frame window class
wndclass.style = CS_HREDRAW | CS_VREDRAW ;
wndclass.lpfnWndProc = FrameWndProc ;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hInstance = hInstance ;
wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = COLOR_APPWORKSPACE + 1 ;
wndclass.lpszMenuName = NULL ;
wndclass.lpszClassName = szFrameClass ;
RegisterClass (&wndclass) ;
// Register the Hello child window class
wndclass.style = CS_HREDRAW | CS_VREDRAW ;
wndclass.lpfnWndProc = HelloWndProc ;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = sizeof (LOCALHANDLE) ;
wndclass.hInstance = hInstance ;
wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = GetStockObject (WHITE_BRUSH) ;
wndclass.lpszMenuName = NULL ;
wndclass.lpszClassName = szHelloClass ;
RegisterClass (&wndclass) ;
// Register the Rect child window class
wndclass.style = CS_HREDRAW | CS_VREDRAW ;
wndclass.lpfnWndProc = RectWndProc ;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = sizeof (LOCALHANDLE) ;
wndclass.hInstance = hInstance ;
wndclass.hIcon = NULL ;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = GetStockObject (WHITE_BRUSH) ;
wndclass.lpszMenuName = NULL ;
wndclass.lpszClassName = szRectClass ;
RegisterClass (&wndclass) ;
}
// Obtain handles to three possible menus & submenus
hMenuInit = LoadMenu (hInst, "MdiMenuInit") ;
hMenuHello = LoadMenu (hInst, "MdiMenuHello") ;
hMenuRect = LoadMenu (hInst, "MdiMenuRect") ;
hMenuInitWindow = GetSubMenu (hMenuInit, INIT_MENU_POS) ;
hMenuHelloWindow = GetSubMenu (hMenuHello, HELLO_MENU_POS) ;
hMenuRectWindow = GetSubMenu (hMenuRect, RECT_MENU_POS) ;
// Load accelerator table
hAccel = LoadAccelerators (hInst, "MdiAccel") ;
// Create the frame window
hwndFrame = CreateWindow (szFrameClass, "MDI Demonstration",
WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, hMenuInit, hInstance, NULL) ;
hwndClient = GetWindow (hwndFrame, GW_CHILD) ;
ShowWindow (hwndFrame, nCmdShow) ;
UpdateWindow (hwndFrame) ;
// Enter the modified message loop
while (GetMessage (&msg, NULL, 0, 0))
{
if (!TranslateMDISysAccel (hwndClient, &msg) &&
!TranslateAccelerator (hwndFrame, hAccel, &msg))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
}
return msg.wParam ;
}
long FAR PASCAL FrameWndProc (HWND hwnd, WORD message, WORD wParam, LONG lPar
{
static HWND hwndClient ;
CLIENTCREATESTRUCT clientcreate ;
FARPROC lpfnEnum ;
HWND hwndChild, hwndNext ;
MDICREATESTRUCT mdicreate ;
switch (message)
{
case WM_CREATE: // Create the client window
clientcreate.hWindowMenu = hMenuInitWindow ;
clientcreate.idFirstChild = IDM_FIRSTCHILD ;
hwndClient = CreateWindow ("MDICLIENT", NULL,
WS_CHILD | WS_CLIPCHILDREN | WS_VISIBLE,
0, 0, 0, 0, hwnd, 1, hInst,
(LPSTR) &clientcreate) ;
return 0 ;
case WM_COMMAND:
switch (wParam)
{
case IDM_NEWHELLO: // Create a Hello child window
mdicreate.szClass = szHelloClass ;
mdicreate.szTitle = "Hello" ;
mdicreate.hOwner = hInst ;
mdicreate.x = CW_USEDEFAULT ;
mdicreate.y = CW_USEDEFAULT ;
mdicreate.cx = CW_USEDEFAULT ;
mdicreate.cy = CW_USEDEFAULT ;
mdicreate.style = 0 ;
mdicreate.lParam = NULL ;
hwndChild = SendMessage (hwndClient, WM_MDICREATE, 0
(LONG) (LPMDICREATESTRUCT) &mdicreate
return 0 ;
case IDM_NEWRECT: // Create a Rect child window
mdicreate.szClass = szRectClass ;
mdicreate.szTitle = "Rectangles" ;
mdicreate.hOwner = hInst ;
mdicreate.x = CW_USEDEFAULT ;
mdicreate.y = CW_USEDEFAULT ;
mdicreate.cx = CW_USEDEFAULT ;
mdicreate.cy = CW_USEDEFAULT ;
mdicreate.style = 0 ;
mdicreate.lParam = NULL ;
hwndChild = SendMessage (hwndClient, WM_MDICREATE,
(LONG) (LPMDICREATESTRUCT) &mdicreate
return 0 ;
case IDM_CLOSE: // Close the active window
hwndChild = LOWORD (SendMessage (hwndClient,
WM_MDIGETACTIVE, 0, 0L)) ;
if (SendMessage (hwndChild, WM_QUERYENDSESSION, 0, 0
SendMessage (hwndClient, WM_MDIDESTROY,
hwndChild, 0L) ;
return 0 ;
case IDM_EXIT: // Exit the program
SendMessage (hwnd, WM_CLOSE, 0, 0L) ;
return 0 ;
// Messages for arranging windows
case IDM_TILE:
SendMessage (hwndClient, WM_MDITILE, 0, 0L) ;
return 0 ;
case IDM_CASCADE:
SendMessage (hwndClient, WM_MDICASCADE, 0, 0L) ;
return 0 ;
case IDM_ARRANGE:
SendMessage (hwndClient, WM_MDIICONARRANGE, 0, 0L) ;
return 0 ;
case IDM_CLOSEALL: // Attempt to close all children
lpfnEnum = MakeProcInstance (CloseEnumProc, hInst) ;
EnumChildWindows (hwndClient, lpfnEnum, 0L) ;
FreeProcInstance (lpfnEnum) ;
return 0 ;
default: // Pass to active child
hwndChild = LOWORD (SendMessage (hwndClient,
WM_MDIGETACTIVE, 0, 0L)) ;
if (IsWindow (hwndChild))
SendMessage (hwndChild, WM_COMMAND,
wParam, lParam) ;
break ; // and then to DefFrameProc
}
break ;
case WM_QUERYENDSESSION:
case WM_CLOSE: // Attempt to close all children
SendMessage (hwnd, WM_COMMAND, IDM_CLOSEALL, 0L) ;
if (NULL != GetWindow (hwndClient, GW_CHILD))
return 0 ;
break ; // ie, call DefFrameProc ;
case WM_DESTROY :
PostQuitMessage (0) ;
return 0 ;
}
// Pass unprocessed messages to DefFrameProc (not DefWindowPro
return DefFrameProc (hwnd, hwndClient, message, wParam, lParam) ;
}
BOOL FAR PASCAL CloseEnumProc (HWND hwnd, LONG lParam)
{
if (GetWindow (hwnd, GW_OWNER)) // check for icon title
return 1 ;
SendMessage (GetParent (hwnd), WM_MDIRESTORE, hwnd, 0L) ;
if (!SendMessage (hwnd, WM_QUERYENDSESSION, 0, 0L))
return 1 ;
SendMessage (GetParent (hwnd), WM_MDIDESTROY, hwnd, 0L) ;
return 1 ;
}
long FAR PASCAL HelloWndProc (HWND hwnd, WORD message, WORD wParam, LONG lPar
{
static COLORREF clrTextArray [] = { RGB (0, 0, 0), RGB (255, 0, 0),
RGB (0, 255, 0), RGB ( 0, 0, 255),
RGB (255, 255, 255) } ;
static HWND hwndClient, hwndFrame ;
HDC hdc ;
HMENU hMenu ;
LOCALHANDLE hHelloData ;
NPHELLODATA npHelloData ;
PAINTSTRUCT ps ;
RECT rect ;
switch (message)
{
case WM_CREATE:
// Allocate memory for window private data
hHelloData = LocalAlloc (LMEM_MOVEABLE | LMEM_ZEROINIT,
sizeof (HELLODATA)) ;
npHelloData = (NPHELLODATA) LocalLock (hHelloData) ;
npHelloData->nColor = IDM_BLACK ;
npHelloData->clrText = RGB (0, 0, 0) ;
LocalUnlock (hHelloData) ;
SetWindowWord (hwnd, 0, hHelloData) ;
// Save some window handles
hwndClient = GetParent (hwnd) ;
hwndFrame = GetParent (hwndClient) ;
return 0 ;
case WM_COMMAND:
switch (wParam)
{
case IDM_BLACK:
case IDM_RED:
case IDM_GREEN:
case IDM_BLUE:
case IDM_WHITE:
// Change the text color
hHelloData = GetWindowWord (hwnd, 0) ;
npHelloData = (NPHELLODATA) LocalLock (hHelloData) ;
hMenu = GetMenu (hwndFrame) ;
CheckMenuItem (hMenu, npHelloData->nColor,
MF_UNCHECKED) ;
npHelloData->nColor = wParam ;
CheckMenuItem (hMenu, npHelloData->nColor,
MF_CHECKED) ;
npHelloData->clrText =
clrTextArray [wParam - IDM_BLACK] ;
LocalUnlock (hHelloData) ;
InvalidateRect (hwnd, NULL, FALSE) ;
}
return 0 ;
case WM_PAINT:
// Paint the window
hdc = BeginPaint (hwnd, &ps) ;
hHelloData = GetWindowWord (hwnd, 0) ;
npHelloData = (NPHELLODATA) LocalLock (hHelloData) ;
SetTextColor (hdc, npHelloData->clrText) ;
LocalUnlock (hHelloData) ;
GetClientRect (hwnd, &rect) ;
DrawText (hdc, "Hello, World!", -1, &rect,
DT_SINGLELINE | DT_CENTER | DT_VCENTER) ;
EndPaint (hwnd, &ps) ;
return 0 ;
case WM_MDIACTIVATE:
// Set the Hello menu if gaining focus
if (wParam == TRUE)
SendMessage (hwndClient, WM_MDISETMENU, 0,
MAKELONG (hMenuHello, hMenuHelloWindow)) ;
// check or uncheck menu item
hHelloData = GetWindowWord (hwnd, 0) ;
npHelloData = (NPHELLODATA) LocalLock (hHelloData) ;
CheckMenuItem (hMenuHello, npHelloData->nColor,
wParam ? MF_CHECKED : MF_UNCHECKED) ;
LocalUnlock (hHelloData) ;
// Set the Init menu if losing focus
if (wParam == FALSE)
SendMessage (hwndClient, WM_MDISETMENU, 0,
MAKELONG (hMenuInit, hMenuInitWindow)) ;
DrawMenuBar (hwndFrame) ;
return 0 ;
case WM_QUERYENDSESSION:
case WM_CLOSE:
if (IDOK != MessageBox (hwnd, "OK to close window?", "Hello",
MB_ICONQUESTION | MB_OKCANCEL))
return 0 ;
break ; // ie, call DefMDIChildProc
case WM_DESTROY:
hHelloData = GetWindowWord (hwnd, 0) ;
LocalFree (hHelloData) ;
return 0 ;
}
// Pass unprocessed message to DefMDIChildProc
return DefMDIChildProc (hwnd, message, wParam, lParam) ;
}
long FAR PASCAL RectWndProc (HWND hwnd, WORD message, WORD wParam, LONG lPara
{
static HWND hwndClient, hwndFrame ;
HPEN hBrush ;
HDC hdc ;
LOCALHANDLE hRectData ;
NPRECTDATA npRectData ;
PAINTSTRUCT ps ;
short xLeft, xRight, yTop, yBottom, nRed, nGreen, nBlue ;
switch (message)
{
case WM_CREATE:
// Allocate memory for window private data
hRectData = LocalAlloc (LMEM_MOVEABLE | LMEM_ZEROINIT,
sizeof (RECTDATA)) ;
SetWindowWord (hwnd, 0, hRectData) ;
// Start the timer going
SetTimer (hwnd, 1, 250, NULL) ;
// Save some window handles
hwndClient = GetParent (hwnd) ;
hwndFrame = GetParent (hwndClient) ;
return 0 ;
case WM_SIZE: // Save the window size
hRectData = GetWindowWord (hwnd, 0) ;
npRectData = (NPRECTDATA) LocalLock (hRectData) ;
npRectData->cxClient = LOWORD (lParam) ;
npRectData->cyClient = HIWORD (lParam) ;
LocalUnlock (hRectData) ;
break ; // WM_SIZE must be processed by DefMDIChildProc
case WM_TIMER: // Display a random rectangle
hRectData = GetWindowWord (hwnd, 0) ;
npRectData = (NPRECTDATA) LocalLock (hRectData) ;
xLeft = rand () % npRectData->cxClient ;
xRight = rand () % npRectData->cxClient ;
yTop = rand () % npRectData->cyClient ;
yBottom = rand () % npRectData->cyClient ;
nRed = rand () & 255 ;
nGreen = rand () & 255 ;
nBlue = rand () & 255 ;
hdc = GetDC (hwnd) ;
hBrush = CreateSolidBrush (RGB (nRed, nGreen, nBlue)) ;
SelectObject (hdc, hBrush) ;
Rectangle (hdc, min (xLeft, xRight), min (yTop, yBottom),
max (xLeft, xRight), max (yTop, yBottom)) ;
ReleaseDC (hwnd, hdc) ;
DeleteObject (hBrush) ;
LocalUnlock (hRectData) ;
return 0 ;
case WM_PAINT: // Clear the window
InvalidateRect (hwnd, NULL, TRUE) ;
hdc = BeginPaint (hwnd, &ps) ;
EndPaint (hwnd, &ps) ;
return 0 ;
case WM_MDIACTIVATE: // Set the appropriate menu
if (wParam == TRUE)
SendMessage (hwndClient, WM_MDISETMENU, 0,
MAKELONG (hMenuRect, hMenuRectWindow)) ;
else
SendMessage (hwndClient, WM_MDISETMENU, 0,
MAKELONG (hMenuInit, hMenuInitWindow)) ;
DrawMenuBar (hwndFrame) ;
return 0 ;
case WM_DESTROY:
hRectData = GetWindowWord (hwnd, 0) ;
LocalFree (hRectData) ;
KillTimer (hwnd, 1) ;
return 0 ;
}
// Pass unprocessed message to DefMDIChildProc
return DefMDIChildProc (hwnd, message, wParam, lParam) ;
}
MENUDEMO.C
CD-ROM Disc Path: \SAMPCODE\PROGWIN\CHAP09\MENUDEMO.C
/*-----------------------------------------
MENUDEMO.C -- Menu Demonstration
(c) Charles Petzold, 1990
-----------------------------------------*/
#include <windows.h>
#include "menudemo.h"
long FAR PASCAL WndProc (HWND, WORD, WORD, LONG) ;
char szAppName [] = "MenuDemo" ;
int PASCAL WinMain (HANDLE hInstance, HANDLE hPrevInstance,
LPSTR lpszCmdLine, int nCmdShow)
{
HWND hwnd ;
MSG msg ;
WNDCLASS wndclass ;
if (!hPrevInstance)
{
wndclass.style = CS_HREDRAW | CS_VREDRAW ;
wndclass.lpfnWndProc = WndProc ;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hInstance = hInstance ;
wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = GetStockObject (WHITE_BRUSH) ;
wndclass.lpszMenuName = szAppName ;
wndclass.lpszClassName = szAppName ;
RegisterClass (&wndclass) ;
}
hwnd = CreateWindow (szAppName, "Menu Demonstration",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL) ;
ShowWindow (hwnd, nCmdShow) ;
UpdateWindow (hwnd) ;
while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
return msg.wParam ;
}
long FAR PASCAL WndProc (HWND hwnd, WORD message, WORD wParam, LONG lParam)
{
static int wColorID [5] = { WHITE_BRUSH, LTGRAY_BRUSH, GRAY_BRUSH,
DKGRAY_BRUSH, BLACK_BRUSH } ;
static WORD wSelection = IDM_WHITE ;
HMENU hMenu ;
switch (message)
{
case WM_COMMAND:
hMenu = GetMenu (hwnd) ;
switch (wParam)
{
case IDM_NEW:
case IDM_OPEN:
case IDM_SAVE:
case IDM_SAVEAS:
MessageBeep (0) ;
return 0 ;
case IDM_EXIT:
SendMessage (hwnd, WM_CLOSE, 0, 0L) ;
return 0 ;
case IDM_UNDO:
case IDM_CUT:
case IDM_COPY:
case IDM_PASTE:
case IDM_CLEAR:
MessageBeep (0) ;
return 0 ;
case IDM_WHITE: // Note: Logic below
case IDM_LTGRAY: // assumes that IDM_WHITE
case IDM_GRAY: // through IDM_BLACK are
case IDM_DKGRAY: // consecutive numbers in
case IDM_BLACK: // the order shown here.
CheckMenuItem (hMenu, wSelection, MF_UNCHECKED) ;
wSelection = wParam ;
CheckMenuItem (hMenu, wSelection, MF_CHECKED) ;
SetClassWord (hwnd, GCW_HBRBACKGROUND,
GetStockObject (wColorID [wParam - IDM_WHITE]))
InvalidateRect (hwnd, NULL, TRUE) ;
return 0 ;
case IDM_START:
if (SetTimer (hwnd, 1, 1000, NULL))
{
EnableMenuItem (hMenu, IDM_START, MF_GRAYED) ;
EnableMenuItem (hMenu, IDM_STOP, MF_ENABLED) ;
}
return 0 ;
case IDM_STOP:
KillTimer (hwnd, 1) ;
EnableMenuItem (hMenu, IDM_START, MF_ENABLED) ;
EnableMenuItem (hMenu, IDM_STOP, MF_GRAYED) ;
return 0 ;
case IDM_HELP:
MessageBox (hwnd, "Help not yet implemented.",
szAppName, MB_ICONINFORMATION | MB_OK) ;
return 0 ;
case IDM_ABOUT:
MessageBox (hwnd, "Menu Demonstration Program.",
szAppName, MB_ICONINFORMATION | MB_OK) ;
return 0 ;
}
break ;
case WM_TIMER:
MessageBeep (0) ;
return 0 ;
case WM_DESTROY :
PostQuitMessage (0) ;
return 0 ;
}
return DefWindowProc (hwnd, message, wParam, lParam) ;
}
MFCREATE.C
CD-ROM Disc Path: \SAMPCODE\PROGWIN\CHAP13\MFCREATE.C
/*-----------------------------------------
MFCREATE.C -- Metafile Creation Program
(c) Charles Petzold, 1990
-----------------------------------------*/
#include <windows.h>
int PASCAL WinMain (HANDLE hInstance, HANDLE hPrevInstance,
LPSTR lpszCmdLine, int nCmdShow)
{
HBRUSH hBrush = CreateSolidBrush (RGB (0, 0, 255)) ;
HDC hdcMeta = CreateMetaFile ("MYLOGO.WMF") ;
Rectangle (hdcMeta, 0, 0, 100, 100) ;
MoveTo (hdcMeta, 0, 0) ;
LineTo (hdcMeta, 100, 100) ;
MoveTo (hdcMeta, 0, 100) ;
LineTo (hdcMeta, 100, 0) ;
SelectObject (hdcMeta, hBrush) ;
Ellipse (hdcMeta, 20, 20, 80, 80) ;
DeleteMetaFile (CloseMetaFile (hdcMeta)) ;
DeleteObject (hBrush) ;
MessageBeep (0) ;
return FALSE ;
}
MFRESORC.C
CD-ROM Disc Path: \SAMPCODE\PROGWIN\CHAP13\MFRESORC.C
/*-----------------------------------------
MFRESORC.C -- Metafile Resource Program
(c) Charles Petzold, 1990
-----------------------------------------*/
#include <windows.h>
long FAR PASCAL WndProc (HWND, WORD, WORD, LONG) ;
int PASCAL WinMain (HANDLE hInstance, HANDLE hPrevInstance,
LPSTR lpszCmdLine, int nCmdShow)
{
static char szAppName [] = "MFResorc" ;
HWND hwnd ;
MSG msg ;
WNDCLASS wndclass ;
if (!hPrevInstance)
{
wndclass.style = CS_HREDRAW | CS_VREDRAW ;
wndclass.lpfnWndProc = WndProc ;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hInstance = hInstance ;
wndclass.hIcon = NULL ;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = GetStockObject (WHITE_BRUSH) ;
wndclass.lpszMenuName = NULL ;
wndclass.lpszClassName = szAppName ;
RegisterClass (&wndclass) ;
}
hwnd = CreateWindow (szAppName, "Metafile Resource Program",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL) ;
ShowWindow (hwnd, nCmdShow) ;
UpdateWindow (hwnd) ;
while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
return msg.wParam ;
}
long FAR PASCAL WndProc (HWND hwnd, WORD message, WORD wParam, LONG lParam)
{
static HANDLE hmf ;
static short cxClient, cyClient ;
HANDLE hInstance, hResource ;
HDC hdc ;
PAINTSTRUCT ps ;
short x, y ;
switch (message)
{
case WM_CREATE:
hInstance = ((LPCREATESTRUCT) lParam) -> hInstance ;
hResource = LoadResource (hInstance,
FindResource (hInstance, "MyLogo", "METAFILE")) ;
LockResource (hResource) ;
hmf = SetMetaFileBits (hResource) ;
UnlockResource (hResource) ;
return 0 ;
case WM_SIZE:
cxClient = LOWORD (lParam) ;
cyClient = HIWORD (lParam) ;
return 0 ;
case WM_PAINT:
hdc = BeginPaint (hwnd, &ps) ;
SetMapMode (hdc, MM_ANISOTROPIC) ;
SetWindowExt (hdc, 1000, 1000) ;
SetViewportExt (hdc, cxClient, cyClient) ;
for (x = 0 ; x < 10 ; x++)
for (y = 0 ; y < 10 ; y++)
{
SetWindowOrg (hdc, -100 * x, -100 * y) ;
PlayMetaFile (hdc, hmf) ;
}
EndPaint (hwnd, &ps) ;
return 0 ;
case WM_DESTROY:
DeleteMetaFile (hmf) ;
PostQuitMessage (0) ;
return 0 ;
}
return DefWindowProc (hwnd, message, wParam, lParam) ;
}
NOPOPUPS.C
CD-ROM Disc Path: \SAMPCODE\PROGWIN\CHAP09\NOPOPUPS.C
/*-------------------------------------------------
NOPOPUPS.C -- Demonstrates No-Popup Nested Menu
(c) Charles Petzold, 1990
-------------------------------------------------*/
#include <windows.h>
#include "nopopups.h"
long FAR PASCAL WndProc (HWND, WORD, WORD, LONG) ;
int PASCAL WinMain (HANDLE hInstance, HANDLE hPrevInstance,
LPSTR lpszCmdLine, int nCmdShow)
{
static char szAppName [] = "NoPopUps" ;
HWND hwnd ;
MSG msg ;
WNDCLASS wndclass ;
if (!hPrevInstance)
{
wndclass.style = CS_HREDRAW | CS_VREDRAW ;
wndclass.lpfnWndProc = WndProc ;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hInstance = hInstance ;
wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = GetStockObject (WHITE_BRUSH) ;
wndclass.lpszMenuName = NULL ;
wndclass.lpszClassName = szAppName ;
RegisterClass (&wndclass) ;
}
hwnd = CreateWindow (szAppName, "No-Popup Nested Menu Demonstration",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL) ;
ShowWindow (hwnd, nCmdShow) ;
UpdateWindow (hwnd) ;
while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
return msg.wParam ;
}
long FAR PASCAL WndProc (HWND hwnd, WORD message, WORD wParam, LONG lParam)
{
static HMENU hMenuMain, hMenuEdit, hMenuFile ;
HANDLE hInstance ;
switch (message)
{
case WM_CREATE:
hInstance = GetWindowWord (hwnd, GWW_HINSTANCE) ;
hMenuMain = LoadMenu (hInstance, "MenuMain") ;
hMenuFile = LoadMenu (hInstance, "MenuFile") ;
hMenuEdit = LoadMenu (hInstance, "MenuEdit") ;
SetMenu (hwnd, hMenuMain) ;
return 0 ;
case WM_COMMAND:
switch (wParam)
{
case IDM_MAIN:
SetMenu (hwnd, hMenuMain) ;
return 0 ;
case IDM_FILE:
SetMenu (hwnd, hMenuFile) ;
return 0 ;
case IDM_EDIT:
SetMenu (hwnd, hMenuEdit) ;
return 0 ;
case IDM_NEW:
case IDM_OPEN:
case IDM_SAVE:
case IDM_SAVEAS:
case IDM_UNDO:
case IDM_CUT:
case IDM_COPY:
case IDM_PASTE:
case IDM_CLEAR:
MessageBeep (0) ;
return 0 ;
}
break ;
case WM_DESTROY:
PostQuitMessage (0) ;
return 0 ;
}
return DefWindowProc (hwnd, message, wParam, lParam) ;
}
PICKFONT.C
CD-ROM Disc Path: \SAMPCODE\PROGWIN\CHAP14\PICKFONT.C
/*-----------------------------------------
PICKFONT.C -- Font Picker Program
(c) Charles Petzold, 1990
-----------------------------------------*/
#include <windows.h>
#include "pickfont.h"
long FAR PASCAL WndProc (HWND, WORD, WORD, LONG) ;
BOOL FAR PASCAL DlgProc (HWND, WORD, WORD, LONG) ;
char szAppName [] = "PickFont" ;
DWORD dwAspectMatch = 0L ;
HWND hDlg ;
LOGFONT lf ;
short nMapMode = IDD_TEXT ;
int PASCAL WinMain (HANDLE hInstance, HANDLE hPrevInstance,
LPSTR lpszCmdLine, int nCmdShow)
{
HWND hwnd ;
MSG msg ;
WNDCLASS wndclass ;
if (!hPrevInstance)
{
wndclass.style = CS_HREDRAW | CS_VREDRAW;
wndclass.lpfnWndProc = WndProc ;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hInstance = hInstance ;
wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = GetStockObject (WHITE_BRUSH) ;
wndclass.lpszMenuName = NULL ;
wndclass.lpszClassName = szAppName ;
RegisterClass (&wndclass) ;
}
hwnd = CreateWindow (szAppName, "Font Picker",
WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL) ;
ShowWindow (hwnd, nCmdShow) ;
UpdateWindow (hwnd) ;
while (GetMessage (&msg, NULL, 0, 0))
{
if (hDlg == 0 || !IsDialogMessage (hDlg, &msg))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
}
return msg.wParam ;
}
void MySetMapMode (HDC hdc)
{
if (nMapMode == IDD_LTWPS)
{
SetMapMode (hdc, MM_ANISOTROPIC) ;
SetWindowExt (hdc, 1440, 1440) ;
SetViewportExt (hdc, GetDeviceCaps (hdc, LOGPIXELSX),
GetDeviceCaps (hdc, LOGPIXELSY)) ;
}
else
SetMapMode (hdc, MM_TEXT + nMapMode - IDD_TEXT) ;
}
void ShowMetrics (HWND hDlg)
{
static TEXTMETRIC tm ;
static struct
{
short nDlgID ;
short *pData ;
}
shorts [] =
{
TM_HEIGHT, &tm.tmHeight,
TM_ASCENT, &tm.tmAscent,
TM_DESCENT, &tm.tmDescent,
TM_INTLEAD, &tm.tmInternalLeading,
TM_EXTLEAD, &tm.tmExternalLeading,
TM_AVEWIDTH, &tm.tmAveCharWidth,
TM_MAXWIDTH, &tm.tmMaxCharWidth,
TM_WEIGHT, &tm.tmWeight,
TM_OVER, &tm.tmOverhang,
TM_DIGX, &tm.tmDigitizedAspectX,
TM_DIGY, &tm.tmDigitizedAspectY
} ;
static char *szFamily [] = { "Don't Care", "Roman", "Swiss",
"Modern", "Script", "Decorative" } ;
BOOL bTrans ;
char szFaceName [LF_FACESIZE] ;
HDC hdc ;
HFONT hFont ;
short i ;
lf.lfHeight = GetDlgItemInt (hDlg, IDD_HEIGHT, &bTrans, TRUE) ;
lf.lfWidth = GetDlgItemInt (hDlg, IDD_WIDTH, &bTrans, FALSE) ;
lf.lfWeight = GetDlgItemInt (hDlg, IDD_WEIGHT, &bTrans, FALSE) ;
lf.lfItalic = (BYTE) (IsDlgButtonChecked (hDlg, IDD_ITALIC) ? 1 : 0)
lf.lfUnderline = (BYTE) (IsDlgButtonChecked (hDlg, IDD_UNDER) ? 1 : 0)
lf.lfStrikeOut = (BYTE) (IsDlgButtonChecked (hDlg, IDD_STRIKE) ? 1 : 0)
GetDlgItemText (hDlg, IDD_FACE, lf.lfFaceName, LF_FACESIZE) ;
dwAspectMatch = IsDlgButtonChecked (hDlg, IDD_ASPECT) ? 1L : 0L ;
hdc = GetDC (hDlg) ;
MySetMapMode (hdc) ;
SetMapperFlags (hdc, dwAspectMatch) ;
hFont = SelectObject (hdc, CreateFontIndirect (&lf)) ;
GetTextMetrics (hdc, &tm) ;
GetTextFace (hdc, sizeof szFaceName, szFaceName) ;
DeleteObject (SelectObject (hdc, hFont)) ;
ReleaseDC (hDlg, hdc) ;
for (i = 0 ; i < sizeof shorts / sizeof shorts [0] ; i++)
SetDlgItemInt (hDlg, shorts[i].nDlgID, *shorts[i].pData, TRUE) ;
SetDlgItemText (hDlg, TM_PITCH, tm.tmPitchAndFamily & 1 ?
"VARIABLE":"FIXED") ;
SetDlgItemText (hDlg, TM_FAMILY, szFamily [tm.tmPitchAndFamily >> 4]) ;
SetDlgItemText (hDlg, TM_CHARSET, tm.tmCharSet ? "OEM" : "ANSI") ;
SetDlgItemText (hDlg, TF_NAME, szFaceName) ;
}
BOOL FAR PASCAL DlgProc (HWND hDlg, WORD message, WORD wParam, LONG lParam)
{
switch (message)
{
case WM_INITDIALOG:
CheckRadioButton (hDlg, IDD_TEXT, IDD_LTWPS, IDD_TEXT) ;
CheckRadioButton (hDlg, IDD_ANSI, IDD_OEM, IDD_ANSI) ;
CheckRadioButton (hDlg, IDD_QDRAFT, IDD_QPROOF, IDD_QDRAFT) ;
CheckRadioButton (hDlg, IDD_PDEF, IDD_PVAR, IDD_PDEF) ;
CheckRadioButton (hDlg, IDD_DONT, IDD_DEC, IDD_DONT) ;
lf.lfEscapement = 0 ;
lf.lfOrientation = 0 ;
lf.lfOutPrecision = OUT_DEFAULT_PRECIS ;
lf.lfClipPrecision = CLIP_DEFAULT_PRECIS ;
ShowMetrics (hDlg) ;
/* fall through */
case WM_SETFOCUS:
SetFocus (GetDlgItem (hDlg, IDD_HEIGHT)) ;
return FALSE ;
case WM_COMMAND:
switch (wParam)
{
case IDD_TEXT:
case IDD_LOMET:
case IDD_HIMET:
case IDD_LOENG:
case IDD_HIENG:
case IDD_TWIPS:
case IDD_LTWPS:
CheckRadioButton (hDlg, IDD_TEXT, IDD_LTWPS, wParam)
nMapMode = wParam ;
break ;
case IDD_ASPECT:
case IDD_ITALIC:
case IDD_UNDER:
case IDD_STRIKE:
CheckDlgButton (hDlg, wParam,
IsDlgButtonChecked (hDlg, wParam) ? 0 : 1) ;
break ;
case IDD_ANSI:
case IDD_OEM:
CheckRadioButton (hDlg, IDD_ANSI, IDD_OEM, wParam) ;
lf.lfCharSet = (BYTE) (wParam == IDD_ANSI ? 0 : 255)
break ;
case IDD_QDRAFT:
case IDD_QDEF:
case IDD_QPROOF:
CheckRadioButton (hDlg, IDD_QDRAFT, IDD_QPROOF,
wParam)
lf.lfQuality = (BYTE) (wParam - IDD_QDRAFT) ;
break ;
case IDD_PDEF:
case IDD_PFIXED:
case IDD_PVAR:
CheckRadioButton (hDlg, IDD_PDEF, IDD_PVAR, wParam)
lf.lfPitchAndFamily &= 0xF0 ;
lf.lfPitchAndFamily |= (BYTE) (wParam - IDD_PDEF) ;
break ;
case IDD_DONT:
case IDD_ROMAN:
case IDD_SWISS:
case IDD_MODERN:
case IDD_SCRIPT:
case IDD_DEC:
CheckRadioButton (hDlg, IDD_DONT, IDD_DEC, wParam) ;
lf.lfPitchAndFamily &= 0x0F ;
lf.lfPitchAndFamily |= (BYTE) (wParam-IDD_DONT << 4)
break ;
case IDD_OK:
ShowMetrics (hDlg) ;
InvalidateRect (GetParent (hDlg), NULL, TRUE) ;
break ;
}
break ;
default:
return FALSE ;
}
return TRUE ;
}
long FAR PASCAL WndProc (HWND hwnd, WORD message, WORD wParam, LONG lParam)
{
static char szText [] =
"AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPqQqRrSsTtUuVvWwXxYyZz"
static short cxClient, cyClient ;
HANDLE hInstance ;
HDC hdc ;
HFONT hFont ;
FARPROC lpfnDlgProc ;
PAINTSTRUCT ps ;
RECT rect ;
switch (message)
{
case WM_CREATE :
hInstance = ((LPCREATESTRUCT) lParam)->hInstance ;
lpfnDlgProc = MakeProcInstance (DlgProc, hInstance) ;
hDlg = CreateDialog (hInstance, szAppName, hwnd, lpfnDlgProc)
return 0 ;
case WM_SETFOCUS:
SetFocus (hDlg) ;
return 0 ;
case WM_PAINT:
hdc = BeginPaint (hwnd, &ps) ;
MySetMapMode (hdc) ;
SetMapperFlags (hdc, dwAspectMatch) ;
GetClientRect (hDlg, &rect) ;
rect.bottom += 1 ;
DPtoLP (hdc, (LPPOINT) &rect, 2) ;
hFont = SelectObject (hdc, CreateFontIndirect (&lf)) ;
TextOut (hdc, rect.left, rect.bottom, szText, 52) ;
DeleteObject (SelectObject (hdc, hFont)) ;
EndPaint (hwnd, &ps) ;
return 0 ;
case WM_DESTROY:
PostQuitMessage (0) ;
return 0 ;
}
return DefWindowProc (hwnd, message, wParam, lParam) ;
}
POEPOEM.C
CD-ROM Disc Path: \SAMPCODE\PROGWIN\CHAP08\POEPOEM.C
/*-------------------------------------------------
POEPOEM.C -- Demonstrates User-Defined Resource
(c) Charles Petzold, 1990
-------------------------------------------------*/
#include <windows.h>
#include "poepoem.h"
long FAR PASCAL WndProc (HWND, WORD, WORD, LONG) ;
char szAppName [10] ;
char szCaption [35] ;
HANDLE hInst ;
int PASCAL WinMain (HANDLE hInstance, HANDLE hPrevInstance,
LPSTR lpszCmdLine, int nCmdShow)
{
HWND hwnd ;
MSG msg ;
WNDCLASS wndclass ;
if (!hPrevInstance)
{
LoadString (hInstance, IDS_APPNAME, szAppName, sizeof szAppName) ;
LoadString (hInstance, IDS_CAPTION, szCaption, sizeof szCaption) ;
wndclass.style = CS_HREDRAW | CS_VREDRAW ;
wndclass.lpfnWndProc = WndProc ;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hInstance = hInstance ;
wndclass.hIcon = LoadIcon (hInstance, szAppName) ;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = GetStockObject (WHITE_BRUSH) ;
wndclass.lpszMenuName = NULL ;
wndclass.lpszClassName = szAppName ;
RegisterClass (&wndclass) ;
}
else
{
GetInstanceData (hPrevInstance, szAppName, sizeof szAppName) ;
GetInstanceData (hPrevInstance, szCaption, sizeof szCaption) ;
}
hInst = hInstance ;
hwnd = CreateWindow (szAppName, szCaption,
WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL) ;
ShowWindow (hwnd, nCmdShow) ;
UpdateWindow (hwnd) ;
while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
return msg.wParam ;
}
long FAR PASCAL WndProc (HWND hwnd, WORD message, WORD wParam, LONG lParam)
{
static HANDLE hResource ;
static HWND hScroll ;
static short nPosition, cxChar, cyChar, cyClient, nNumLines, xScroll ;
char szPoemRes [15] ;
char far *lpText ;
HDC hdc ;
PAINTSTRUCT ps ;
RECT rect ;
TEXTMETRIC tm ;
switch (message)
{
case WM_CREATE:
hdc = GetDC (hwnd) ;
GetTextMetrics (hdc, &tm) ;
cxChar = tm.tmAveCharWidth ;
cyChar = tm.tmHeight + tm.tmExternalLeading ;
ReleaseDC (hwnd, hdc) ;
xScroll = GetSystemMetrics (SM_CXVSCROLL) ;
hScroll = CreateWindow ("scrollbar", NULL,
WS_CHILD | WS_VISIBLE | SBS_VERT,
0, 0, 0, 0,
hwnd, 1, hInst, NULL) ;
LoadString (hInst, IDS_POEMRES, szPoemRes, sizeof szPoemRes) ;
hResource = LoadResource (hInst,
FindResource (hInst, szPoemRes, "TEXT")) ;
lpText = LockResource (hResource) ;
nNumLines = 0 ;
while (*lpText != '\\' && *lpText != '\0')
{
if (*lpText == '\n')
nNumLines ++ ;
lpText = AnsiNext (lpText) ;
}
*lpText = '\0' ;
GlobalUnlock (hResource) ;
SetScrollRange (hScroll, SB_CTL, 0, nNumLines, FALSE) ;
SetScrollPos (hScroll, SB_CTL, 0, FALSE) ;
return 0 ;
case WM_SIZE:
MoveWindow (hScroll, LOWORD (lParam) - xScroll, 0,
xScroll, cyClient = HIWORD (lParam), TRUE) ;
SetFocus (hwnd) ;
return 0 ;
case WM_SETFOCUS:
SetFocus (hScroll) ;
return 0 ;
case WM_VSCROLL:
switch (wParam)
{
case SB_TOP:
nPosition = 0 ;
break ;
case SB_BOTTOM:
nPosition = nNumLines ;
break ;
case SB_LINEUP:
nPosition -= 1 ;
break ;
case SB_LINEDOWN:
nPosition += 1 ;
break ;
case SB_PAGEUP:
nPosition -= cyClient / cyChar ;
break ;
case SB_PAGEDOWN:
nPosition += cyClient / cyChar ;
break ;
case SB_THUMBPOSITION:
nPosition = LOWORD (lParam) ;
break ;
}
nPosition = max (0, min (nPosition, nNumLines)) ;
if (nPosition != GetScrollPos (hScroll, SB_CTL))
{
SetScrollPos (hScroll, SB_CTL, nPosition, TRUE) ;
InvalidateRect (hwnd, NULL, TRUE) ;
}
return 0 ;
case WM_PAINT:
hdc = BeginPaint (hwnd, &ps) ;
lpText = LockResource (hResource) ;
GetClientRect (hwnd, &rect) ;
rect.left += cxChar ;
rect.top += cyChar * (1 - nPosition) ;
DrawText (hdc, lpText, -1, &rect, DT_EXTERNALLEADING) ;
GlobalUnlock (hResource) ;
EndPaint (hwnd, &ps) ;
return 0 ;
case WM_DESTROY:
FreeResource (hResource) ;
PostQuitMessage (0) ;
return 0 ;
}
return DefWindowProc (hwnd, message, wParam, lParam) ;
}
POORMENU.C
CD-ROM Disc Path: \SAMPCODE\PROGWIN\CHAP09\POORMENU.C
/*-----------------------------------------
POORMENU.C -- The Poor Person's Menu
(c) Charles Petzold, 1990
-----------------------------------------*/
#include <windows.h>
#define IDM_ABOUT 1
#define IDM_HELP 2
#define IDM_REMOVE 3
long FAR PASCAL WndProc (HWND, WORD, WORD, LONG) ;
static char szAppName [] = "PoorMenu" ;
int PASCAL WinMain (HANDLE hInstance, HANDLE hPrevInstance,
LPSTR lpszCmdLine, int nCmdShow)
{
HMENU hMenu ;
HWND hwnd ;
MSG msg ;
WNDCLASS wndclass ;
if (!hPrevInstance)
{
wndclass.style = CS_HREDRAW | CS_VREDRAW ;
wndclass.lpfnWndProc = WndProc ;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hInstance = hInstance ;
wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = GetStockObject (WHITE_BRUSH) ;
wndclass.lpszMenuName = NULL ;
wndclass.lpszClassName = szAppName ;
RegisterClass (&wndclass) ;
}
hwnd = CreateWindow (szAppName, "The Poor-Person's Menu",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL) ;
hMenu = GetSystemMenu (hwnd, FALSE) ;
AppendMenu (hMenu, MF_SEPARATOR, 0, NULL) ;
AppendMenu (hMenu, MF_STRING, IDM_ABOUT, "About...") ;
AppendMenu (hMenu, MF_STRING, IDM_HELP, "Help...") ;
AppendMenu (hMenu, MF_STRING, IDM_REMOVE, "Remove Additions") ;
ShowWindow (hwnd, nCmdShow) ;
UpdateWindow (hwnd) ;
while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
return msg.wParam ;
}
long FAR PASCAL WndProc (HWND hwnd, WORD message, WORD wParam, LONG lParam)
{
switch (message)
{
case WM_SYSCOMMAND:
switch (wParam)
{
case IDM_ABOUT:
MessageBox (hwnd, "A Poor-Person's Menu Program.",
szAppName, MB_OK | MB_ICONEXCLAMATION) ;
return 0 ;
case IDM_HELP:
MessageBox (hwnd, "Help not yet implemented.",
szAppName, MB_OK | MB_ICONEXCLAMATION) ;
return 0 ;
case IDM_REMOVE:
GetSystemMenu (hwnd, TRUE) ;
return 0 ;
}
break ;
case WM_DESTROY:
PostQuitMessage (0) ;
return 0 ;
}
return DefWindowProc (hwnd, message, wParam, lParam) ;
}
POPMENU.C
CD-ROM Disc Path: \SAMPCODE\PROGWIN\CHAP09\POPMENU.C
/*----------------------------------------
POPMENU.C -- Popup Menu Demonstration
(c) Charles Petzold, 1990
----------------------------------------*/
#include <windows.h>
#include "popmenu.h"
long FAR PASCAL WndProc (HWND, WORD, WORD, LONG) ;
char szAppName [] = "PopMenu" ;
HANDLE hInst ;
int PASCAL WinMain (HANDLE hInstance, HANDLE hPrevInstance,
LPSTR lpszCmdLine, int nCmdShow)
{
HWND hwnd ;
MSG msg ;
WNDCLASS wndclass ;
if (!hPrevInstance)
{
wndclass.style = CS_HREDRAW | CS_VREDRAW ;
wndclass.lpfnWndProc = WndProc ;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hInstance = hInstance ;
wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = GetStockObject (WHITE_BRUSH) ;
wndclass.lpszMenuName = NULL ;
wndclass.lpszClassName = szAppName ;
RegisterClass (&wndclass) ;
}
hInst = hInstance ;
hwnd = CreateWindow (szAppName, "Popup Menu Demonstration",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL) ;
ShowWindow (hwnd, nCmdShow) ;
UpdateWindow (hwnd) ;
while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
return msg.wParam ;
}
long FAR PASCAL WndProc (HWND hwnd, WORD message, WORD wParam, LONG lParam)
{
static HMENU hMenu ;
static int wColorID [5] = { WHITE_BRUSH, LTGRAY_BRUSH, GRAY_BRUSH,
DKGRAY_BRUSH, BLACK_BRUSH } ;
static WORD wSelection = IDM_WHITE ;
POINT point ;
switch (message)
{
case WM_CREATE:
hMenu = LoadMenu (hInst, szAppName) ;
hMenu = GetSubMenu (hMenu, 0) ;
return 0 ;
case WM_RBUTTONDOWN:
point = MAKEPOINT (lParam) ;
ClientToScreen (hwnd, &point) ;
TrackPopupMenu (hMenu, 0, point.x, point.y, 0, hwnd, NULL) ;
return 0 ;
case WM_COMMAND:
switch (wParam)
{
case IDM_NEW:
case IDM_OPEN:
case IDM_SAVE:
case IDM_SAVEAS:
case IDM_UNDO:
case IDM_CUT:
case IDM_COPY:
case IDM_PASTE:
case IDM_CLEAR:
MessageBeep (0) ;
return 0 ;
case IDM_WHITE: // Note: Logic below
case IDM_LTGRAY: // assumes that IDM_WHITE
case IDM_GRAY: // through IDM_BLACK are
case IDM_DKGRAY: // consecutive numbers in
case IDM_BLACK: // the order shown here.
CheckMenuItem (hMenu, wSelection, MF_UNCHECKED) ;
wSelection = wParam ;
CheckMenuItem (hMenu, wSelection, MF_CHECKED) ;
SetClassWord (hwnd, GCW_HBRBACKGROUND,
GetStockObject (wColorID [wParam - IDM_WHITE]))
InvalidateRect (hwnd, NULL, TRUE) ;
return 0 ;
case IDM_ABOUT:
MessageBox (hwnd, "Popup Menu Demonstration Program.
szAppName, MB_ICONINFORMATION | MB_OK) ;
return 0 ;
case IDM_EXIT:
SendMessage (hwnd, WM_CLOSE, 0, 0L) ;
return 0 ;
case IDM_HELP:
MessageBox (hwnd, "Help not yet implemented.",
szAppName, MB_ICONINFORMATION | MB_OK) ;
return 0 ;
}
break ;
case WM_DESTROY :
PostQuitMessage (0) ;
return 0 ;
}
return DefWindowProc (hwnd, message, wParam, lParam) ;
}
POPPAD.C
CD-ROM Disc Path: \SAMPCODE\PROGWIN\CHAP10\POPPAD.C
/*---------------------------------------
POPPAD.C -- Popup Editor
(c) Charles Petzold, 1990
---------------------------------------*/
#include <windows.h>
#include "poppad.h"
#define EDITID 1
long FAR PASCAL WndProc (HWND, WORD, WORD, LONG);
BOOL ReadFile (HANDLE, HWND, HWND, POFSTRUCT, char *, BOOL) ;
BOOL WriteFile (HANDLE, HWND, HWND, POFSTRUCT, char *, BOOL) ;
BOOL PrintFile (HANDLE, HWND, HWND, char *) ;
LPSTR lstrrchr (LPSTR, char) ;
char szAppName [] = "PopPad" ;
char szFileSpec [] = "*.TXT" ;
char szUntitled [] = "(untitled)" ;
int PASCAL WinMain (HANDLE hInstance, HANDLE hPrevInstance,
LPSTR lpszCmdLine, int nCmdShow)
{
MSG msg;
HWND hwnd ;
HANDLE hAccel ;
WNDCLASS wndclass ;
if (!hPrevInstance)
{
wndclass.style = CS_HREDRAW | CS_VREDRAW ;
wndclass.lpfnWndProc = WndProc ;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hInstance = hInstance ;
wndclass.hIcon = LoadIcon (hInstance, szAppName) ;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = GetStockObject (WHITE_BRUSH) ;
wndclass.lpszMenuName = szAppName ;
wndclass.lpszClassName = szAppName ;
RegisterClass (&wndclass) ;
}
hwnd = CreateWindow (szAppName, NULL,
WS_OVERLAPPEDWINDOW,
GetSystemMetrics (SM_CXSCREEN) / 4,
GetSystemMetrics (SM_CYSCREEN) / 4,
GetSystemMetrics (SM_CXSCREEN) / 2,
GetSystemMetrics (SM_CYSCREEN) / 2,
NULL, NULL, hInstance, lpszCmdLine) ;
ShowWindow (hwnd, nCmdShow) ;
UpdateWindow (hwnd);
hAccel = LoadAccelerators (hInstance, szAppName) ;
while (GetMessage (&msg, NULL, 0, 0))
{
if (!TranslateAccelerator (hwnd, hAccel, &msg))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
}
return msg.wParam ;
}
BOOL FAR PASCAL AboutDlgProc (HWND hDlg, WORD message, WORD wParam, LONG lPar
{
switch (message)
{
case WM_INITDIALOG:
return TRUE ;
case WM_COMMAND:
switch (wParam)
{
case IDOK:
EndDialog (hDlg, 0) ;
return TRUE ;
}
break ;
}
return FALSE ;
}
void DoCaption (HWND hwnd, char *szFileName)
{
char szCaption [40] ;
wsprintf (szCaption, "%s - %s", (LPSTR) szAppName,
(LPSTR) (szFileName [0] ? szFileName : szUntitled)) ;
SetWindowText (hwnd, szCaption) ;
}
short AskAboutSave (HWND hwnd, char *szFileName)
{
char szBuffer [40] ;
short nReturn ;
wsprintf (szBuffer, "Save current changes: %s",
(LPSTR) (szFileName [0] ? szFileName : szUntitled)) ;
if (IDYES == (nReturn = MessageBox (hwnd, szBuffer, szAppName,
MB_YESNOCANCEL | MB_ICONQUESTION)))
if (!SendMessage (hwnd, WM_COMMAND, IDM_SAVE, 0L))
return IDCANCEL ;
return nReturn ;
}
long FAR PASCAL WndProc (HWND hwnd, WORD message, WORD wParam, LONG lParam)
{
static BOOL bNeedSave = FALSE ;
static char szRealFileName [16] ;
static FARPROC lpfnAboutDlgProc ;
static HANDLE hInst ;
static HWND hwndEdit ;
char szFileName [16] ;
LONG lSelect ;
OFSTRUCT of ;
WORD wEnable ;
switch (message)
{
case WM_CREATE:
hInst = ((LPCREATESTRUCT) lParam)->hInstance ;
lpfnAboutDlgProc = MakeProcInstance (AboutDlgProc, hInst) ;
hwndEdit = CreateWindow ("edit", NULL,
WS_CHILD | WS_VISIBLE | WS_HSCROLL | WS_VSCROLL |
WS_BORDER | ES_LEFT | ES_MULTILINE |
ES_AUTOHSCROLL | ES_AUTOVSCROLL,
0, 0, 0, 0,
hwnd, EDITID, hInst, NULL) ;
SendMessage (hwndEdit, EM_LIMITTEXT, 32000, 0L) ;
if (lstrlen (((LPCREATESTRUCT) lParam)->lpCreateParams))
{
OpenFile (((LPCREATESTRUCT) lParam)->lpCreateParams,
&of, OF_PARSE) ;
lstrcpy (szFileName,
AnsiNext (lstrrchr (of.szPathName, '\\'))) ;
if (ReadFile (hInst, hwnd, hwndEdit, &of,
szFileName, FALSE))
lstrcpy (szRealFileName, szFileName) ;
}
DoCaption (hwnd, szRealFileName) ;
return 0 ;
case WM_SETFOCUS:
SetFocus (hwndEdit) ;
return 0 ;
case WM_SIZE:
MoveWindow (hwndEdit, 0, 0, LOWORD (lParam),
HIWORD (lParam), TRUE) ;
return 0 ;
case WM_INITMENUPOPUP:
if (lParam == 1)
{
EnableMenuItem (wParam, IDM_UNDO,
SendMessage (hwndEdit, EM_CANUNDO, 0, 0L) ?
MF_ENABLED : MF_GRAYED) ;
EnableMenuItem (wParam, IDM_PASTE,
IsClipboardFormatAvailable (CF_TEXT) ?
MF_ENABLED : MF_GRAYED) ;
lSelect = SendMessage (hwndEdit, EM_GETSEL, 0, 0L) ;
if (HIWORD (lSelect) == LOWORD (lSelect))
wEnable = MF_GRAYED ;
else
wEnable = MF_ENABLED ;