README.TXT

The \Mssdk\Samples\Begin directory contains samples for building
basic Win32 applications including:

* Generic Win32 DLL
* Generic Win32 EXE
* Basic Win32 Help

The build environment (headers, libraries, and minimum build
tools) for the Platform SDK must be installed in order to build
any of the samples in the \Mssdk\Samples directory. The build
environment can be installed from the readme.htm or by running
setup.exe on the root of the Platform SDK compact disc. The most
recent version of the build environment is also available at
http://www.microsoft.com/msdn/sdk/platform.htm.

Some components may also require you to install runtimes, depending
on the platform on which you are trying to run the sample.
Redistributables are available in the \Mssdk\Redist subdirectory
on the Platform SDK compact disc.

Documentation for the components listed above can be installed
from the Platform SDK compact disc, or can be viewed online at
http://premium.microsoft.com/msdn/library/. This is a free service;
registration is necessary.

If you do not see any subdirectories in the \Mssdk\Samples\Begin
node, you'll need to install the COM and ActiveX components
from the Platform SDK compact disc or download and install them
from http://www.microsoft.com/msdn/sdk/platform.htm.


README.TXT

DLL Sample

The SELECT sample shows you how to create a very simple DLL.


DEMO.H

/******************************************************************************\
*       This is a part of the Microsoft Source Code Samples.
*       Copyright 1993 - 1998 Microsoft Corporation.
*       All rights reserved.
*       This source code is only intended as a supplement to
*       Microsoft Development Tools and/or WinHelp documentation.
*       See these sources for detailed information regarding the
*       Microsoft samples programs.
\******************************************************************************/

#define IDM_BOX     101
#define IDM_BLOCK   102
#define IDM_RETAIN  103
#define IDM_ABOUT   104

#define IDS_APPNAME     1001
#define IDS_NOMEM       1002

BOOL DemoInit(HANDLE);
LONG APIENTRY DemoWndProc(HWND, UINT, UINT, LONG);
BOOL APIENTRY About(HWND, UINT, UINT, LONG);


DEMO.C

/******************************************************************************\
*       This is a part of the Microsoft Source Code Samples.
*       Copyright 1993 - 1998 Microsoft Corporation.
*       All rights reserved.
*       This source code is only intended as a supplement to
*       Microsoft Development Tools and/or WinHelp documentation.
*       See these sources for detailed information regarding the
*       Microsoft samples programs.
\******************************************************************************/

/****************************************************************************

    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 APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR lpCmdLine,
                     int nCmdShow)
{

    HWND hWnd;
    MSG msg;
    CHAR szAppName[64];

    UNREFERENCED_PARAMETER(lpCmdLine);

    if (!hPrevInstance)
        if (!DemoInit(hInstance))
            return (0);

    hInst = hInstance;
    LoadString(hInstance, IDS_APPNAME, szAppName, sizeof(szAppName));

    hWnd = CreateWindow("Demo",
        szAppName,
        WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        NULL,
        NULL,
        hInstance,
        NULL);

    if (!hWnd)
        return (0);

    ShowWindow(hWnd, nCmdShow);
    UpdateWindow(hWnd);

    while (GetMessage(&msg, NULL, 0, 0)) {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return (msg.wParam);
}

/****************************************************************************

    FUNCTION: DemoInit(HANDLE)

    PURPOSE: Initializes window data and registers window class

****************************************************************************/

BOOL DemoInit(HANDLE hInstance)
{
    HANDLE hMemory;
    PWNDCLASS pWndClass;
    BOOL bSuccess;
    CHAR lpBuffer[128];

    hMemory = LocalAlloc(LPTR, sizeof(WNDCLASS));
    if(!hMemory){
        LoadString(hInst, IDS_NOMEM, lpBuffer, sizeof(lpBuffer));
        MessageBox(NULL, lpBuffer, NULL, MB_OK | MB_ICONHAND);
        return(FALSE);
    }

    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 = 0;
    pWndClass->lpfnWndProc = (WNDPROC)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 APIENTRY DemoWndProc(
    HWND hWnd,
    UINT message,
    UINT wParam,
    LONG lParam)
{
    FARPROC lpProcAbout;
    HMENU hMenu;

    switch (message) {

        case WM_COMMAND:

            // LOWORD added for portability

            switch (LOWORD(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((FARPROC)About, hInst);
                    DialogBox(hInst, "AboutBox", hWnd, (DLGPROC)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, MAKEMPOINT(lParam), &Rect,
                (wParam & MK_SHIFT) ? SL_EXTEND | Shape : Shape);
            break;

        case WM_MOUSEMOVE:
            if (bTrack)
                UpdateSelection(hWnd, MAKEMPOINT(lParam), &Rect, Shape);
            break;

        case WM_LBUTTONUP:
       if (bTrack)
               EndSelection(MAKEMPOINT(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(0);
            break;

        default:
            return (DefWindowProc(hWnd, message, wParam, lParam));
    }
    return (0);
}

/****************************************************************************

    FUNCTION: About(HWND, unsigned, WORD, LONG)

    PURPOSE:  Processes messages for "About" dialog box

    MESSAGES:

        WM_INITDIALOG - initialize dialog box
        WM_COMMAND    - Input received

****************************************************************************/

BOOL APIENTRY About(
    HWND hDlg,
    UINT message,
    UINT wParam,
    LONG lParam)
{
    switch (message) {
        case WM_INITDIALOG:
            return (TRUE);

        case WM_COMMAND:
            // LOWORD added for portability
            if (LOWORD(wParam) == IDOK
             || LOWORD(wParam) == IDCANCEL) {
                EndDialog(hDlg, TRUE);
                return (TRUE);
            }
            return (TRUE);
    }
    return (FALSE);
        UNREFERENCED_PARAMETER(lParam);
}


SELECT.C

/******************************************************************************\
*       This is a part of the Microsoft Source Code Samples.
*       Copyright 1993 - 1998 Microsoft Corporation.
*       All rights reserved.
*       This source code is only intended as a supplement to
*       Microsoft Development Tools and/or WinHelp documentation.
*       See these sources for detailed information regarding the
*       Microsoft samples programs.
\******************************************************************************/

/****************************************************************************

    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: DllMain(HANDLE, DWORD, LPVOID)

   PURPOSE:  DllMain is called by Windows when
             the DLL is initialized, Thread Attached, and other times.
             Refer to SDK documentation, as to the different ways this
             may be called.

             The DllMain function should perform additional initialization
             tasks required by the DLL.  In this example, no initialization
             tasks are required.  DllMain should return a value of 1 if
             the initialization is successful.

*******************************************************************************/
BOOL APIENTRY DllMain(HANDLE hInst, DWORD ul_reason_being_called, LPVOID lpReserved)
{
    return 1;
        UNREFERENCED_PARAMETER(hInst);
        UNREFERENCED_PARAMETER(ul_reason_being_called);
        UNREFERENCED_PARAMETER(lpReserved);
}

/****************************************************************************

    FUNCTION: StartSelection(HWND, POINT, LPRECT, int)

    PURPOSE: Begin selection of region

****************************************************************************/

INT APIENTRY StartSelection(
    HWND hWnd,
    MPOINT 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);
    return 1;
}

/****************************************************************************

    FUNCTION: UpdateSelection(HWND, POINT, LPRECT, int) - update selection area

    PURPOSE: Update selection

****************************************************************************/

INT APIENTRY UpdateSelection(
    HWND hWnd,
    MPOINT ptCurrent,
    LPRECT lpSelectRect,
    INT fFlags)
{
    HDC hDC;
    SHORT OldROP;

    hDC = GetDC(hWnd);

    switch (fFlags & SL_TYPE) {

        case SL_BOX:
            OldROP = (SHORT)SetROP2(hDC, R2_NOTXORPEN);
            MoveToEx(hDC, lpSelectRect->left, lpSelectRect->top, NULL);
            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);
    return 1;
}

/****************************************************************************

    FUNCTION: EndSelection(POINT, LPRECT)

    PURPOSE: End selection of region, release capture of mouse movement

****************************************************************************/

INT APIENTRY EndSelection(
    MPOINT ptCurrent,
    LPRECT lpSelectRect)
{
    lpSelectRect->right = ptCurrent.x;
    lpSelectRect->bottom = ptCurrent.y;
    ReleaseCapture();
    return 1;
}

/****************************************************************************

    FUNCTION: ClearSelection(HWND, LPRECT, int) - clear selection area

    PURPOSE: Clear the current selection

****************************************************************************/

INT APIENTRY ClearSelection(
    HWND hWnd,
    LPRECT lpSelectRect,
    INT fFlags)
{
    HDC hDC;
    INT2DWORD OldROP;

    hDC = GetDC(hWnd);
    switch (fFlags & SL_TYPE) {

        case SL_BOX:
            OldROP = SetROP2(hDC, R2_NOTXORPEN);
            MoveToEx(hDC, lpSelectRect->left, lpSelectRect->top, NULL);
            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);
    return 1;
}


SELECT.H

/******************************************************************************\
*       This is a part of the Microsoft Source Code Samples.
*       Copyright 1993 - 1998 Microsoft Corporation.
*       All rights reserved.
*       This source code is only intended as a supplement to
*       Microsoft Development Tools and/or WinHelp documentation.
*       See these sources for detailed information regarding the
*       Microsoft samples programs.
\******************************************************************************/

/* These defines determine the meaning of the fFlags variable.  The low byte
 * is used for the various types of "boxes" to draw.  The high byte is
 * available for special commands.
 */

#define SL_BOX    1             /* Draw a solid border around the rectangle  */
#define SL_BLOCK  2             /* Draw a solid rectangle                    */

#define SL_EXTEND 256           /* Extend the current pattern                */

#define SL_TYPE    0x00FF       /* Mask out everything but the type flags    */
#define SL_SPECIAL 0xFF00       /* Mask out everything but the special flags */

// Temporary porting macros

#define INT2DWORD               DWORD
typedef POINTS MPOINT;
#define MAKEMPOINT(l)           (*((MPOINT *)&(l)))
#define MPOINT2POINT(mpt, pt)   ((pt).x = (mpt).x, (pt).y = (mpt).y)
#define POINT2MPOINT(pt, mpt)   ((mpt).x = (SHORT)(pt).x, (mpt).y = (SHORT)(pt).y)

int APIENTRY StartSelection(HWND, MPOINT, LPRECT, int);
int APIENTRY UpdateSelection(HWND, MPOINT, LPRECT, int);
int APIENTRY EndSelection(MPOINT, LPRECT);
int APIENTRY ClearSelection(HWND, LPRECT, int);


README.TXT

Generic Win32-based Application

The GENERIC sample is a generic Win32-based application with a menu and an
About box, but without any real functionality. The sample demonstrates the
basic steps that are used to create the application.

The files included in this sample are:

GENERIC.C - The .C source file
GENERIC.H - The .H file for the sample
RESOURCE.H - The .H file created by VC++ 2.0
GENERIC.DEF - The definition file
GENERIC.RC - Contains resource information such as menus and dialog boxes
GENERIC.HPJ - The Help file source
GENERIC.CNT - The contents list for the Help file
GENERIC.RTF -  A rich text format file used for Help
GENERIC.MAK - A Microsoft Visual C++ 2.0 make file
MAKEFILE - A command line make file
MAKEHELP.BAT - A batch file that makes the Help file
GENERIC.ICO - The icon for the GENERIC sample
SMALL.ICO - The small-icon for the GENERIC sample
GENERIC.BMP - A bitmap for the GENERIC sample
HELP.BMP - A bitmap for the Help file


GENERIC.C

//THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
//ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
//THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//
// Copyright 1994 - 1998 Microsoft Corporation.  All Rights Reserved.
//
// PROGRAM: Generic.c
//
// PURPOSE: Illustrates the 'minimum' functionality of a well-behaved Win32 application..
//
// PLATFORMS:  Windows 95, Windows NT, Win32s
//
// FUNCTIONS:
//    WinMain() - calls initialization function, processes message loop
//    InitApplication() - Initializes window data nd registers window
//    InitInstance() -saves instance handle and creates main window
//    WindProc() Processes messages
//    About() - Process menssages for "About" dialog box
//    MyRegisterClass() - Registers the application's window class
//    CenterWindow() -  Centers one window over another
//
// SPECIAL INSTRUCTIONS: N/A
//
#define APPNAME "Generic"

// Windows Header Files:
#include <windows.h>

// C RunTime Header Files
#include <stdlib.h>
#include <malloc.h>
#include <memory.h>

// Local Header Files
#include "generic.h"

// Makes it easier to determine appropriate code paths:
#if defined (WIN32)
   #define IS_WIN32 TRUE
#else
   #define IS_WIN32 FALSE
#endif
#define IS_NT      IS_WIN32 && (BOOL)(GetVersion() < 0x80000000)
#define IS_WIN32S  IS_WIN32 && (BOOL)(!(IS_NT) && (LOBYTE(LOWORD(GetVersion()))<4))
#define IS_WIN95 (BOOL)(!(IS_NT) && !(IS_WIN32S)) && IS_WIN32

// Global Variables:

HINSTANCE hInst;      // current instance
char szAppName[100];  // Name of the app
char szTitle[100];    // The title bar text

// Foward declarations of functions included in this code module:

ATOM MyRegisterClass(CONST WNDCLASS*);
BOOL InitApplication(HINSTANCE);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK About(HWND, UINT, WPARAM, LPARAM);
BOOL CenterWindow (HWND, HWND);
LPTSTR   GetStringRes (int id);

//
//  FUNCTION: WinMain(HANDLE, HANDLE, LPSTR, int)
//
//  PURPOSE: Entry point for the application.
//
//  COMMENTS:
//
// This function initializes the application and processes the
// message loop.
//
int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
{
   MSG msg;
   HANDLE hAccelTable;

   // Initialize global strings
   lstrcpy (szAppName, APPNAME);
   LoadString (hInstance, IDS_APP_TITLE, szTitle, 100);

   if (!hPrevInstance) {
      // Perform instance initialization:
      if (!InitApplication(hInstance)) {
         return (FALSE);
      }
   }

   // Perform application initialization:
   if (!InitInstance(hInstance, nCmdShow)) {
      return (FALSE);
   }

   hAccelTable = LoadAccelerators (hInstance, szAppName);

   // Main message loop:
   while (GetMessage(&msg, NULL, 0, 0)) {
      if (!TranslateAccelerator (msg.hwnd, hAccelTable, &msg)) {
         TranslateMessage(&msg);
         DispatchMessage(&msg);
      }
   }

   return (msg.wParam);

   lpCmdLine; // This will prevent 'unused formal parameter' warnings
}

//
//  FUNCTION: MyRegisterClass(CONST WNDCLASS*)
//
//  PURPOSE: Registers the window class.
//
//  COMMENTS:
//
//    This function and its usage is only necessary if you want this code
//    to be compatible with Win32 systems prior to the 'RegisterClassEx'
// function that was added to Windows 95. It is important to call this function
//    so that the application will get 'well formed' small icons associated
//    with it.
//
ATOM MyRegisterClass(CONST WNDCLASS *lpwc)
{
   HANDLE  hMod;
   FARPROC proc;
   WNDCLASSEX wcex;

   hMod = GetModuleHandle ("USER32");
   if (hMod != NULL) {

#if defined (UNICODE)
      proc = GetProcAddress (hMod, "RegisterClassExW");
#else
      proc = GetProcAddress (hMod, "RegisterClassExA");
#endif

      if (proc != NULL) {

         wcex.style         = lpwc->style;
         wcex.lpfnWndProc   = lpwc->lpfnWndProc;
         wcex.cbClsExtra    = lpwc->cbClsExtra;
         wcex.cbWndExtra    = lpwc->cbWndExtra;
         wcex.hInstance     = lpwc->hInstance;
         wcex.hIcon         = lpwc->hIcon;
         wcex.hCursor       = lpwc->hCursor;
         wcex.hbrBackground = lpwc->hbrBackground;
                     wcex.lpszMenuName  = lpwc->lpszMenuName;
         wcex.lpszClassName = lpwc->lpszClassName;

         // Added elements for Windows 95:
         wcex.cbSize = sizeof(WNDCLASSEX);
         wcex.hIconSm = LoadIcon(wcex.hInstance, "SMALL");

         return (*proc)(&wcex);//return RegisterClassEx(&wcex);
      }
   }
   return (RegisterClass(lpwc));
}

//
//  FUNCTION: InitApplication(HANDLE)
//
//  PURPOSE: Initializes window data and registers window class
//
//  COMMENTS:
//
//       In this function, we initialize a window class by filling out a data
//       structure of type WNDCLASS and calling either RegisterClass or
//       the internal MyRegisterClass.
//
BOOL InitApplication(HINSTANCE hInstance)
{
    WNDCLASS  wc;
    HWND      hwnd;

    // Win32 will always set hPrevInstance to NULL, so lets check
    // things a little closer. This is because we only want a single
    // version of this app to run at a time
    hwnd = FindWindow (szAppName, szTitle);
    if (hwnd) {
        // We found another version of ourself. Lets defer to it:
        if (IsIconic(hwnd)) {
            ShowWindow(hwnd, SW_RESTORE);
        }
        SetForegroundWindow (hwnd);

        // If this app actually had any functionality, we would
        // also want to communicate any action that our 'twin'
        // should now perform based on how the user tried to
        // execute us.
        return FALSE;
        }

        // Fill in window class structure with parameters that describe
        // the main window.
        wc.style         = CS_HREDRAW | CS_VREDRAW;
        wc.lpfnWndProc   = (WNDPROC)WndProc;
        wc.cbClsExtra    = 0;
        wc.cbWndExtra    = 0;
        wc.hInstance     = hInstance;
        wc.hIcon         = LoadIcon (hInstance, szAppName);
        wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
        wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);

        // Since Windows95 has a slightly different recommended
        // format for the 'Help' menu, lets put this in the alternate menu like this:
        if (IS_WIN95) {
   wc.lpszMenuName  = "WIN95";
        } else {
   wc.lpszMenuName  = szAppName;
        }
        wc.lpszClassName = szAppName;

        // Register the window class and return success/failure code.
        if (IS_WIN95) {
   return MyRegisterClass(&wc);
        } else {
   return RegisterClass(&wc);
        }
}

//
//   FUNCTION: InitInstance(HANDLE, int)
//
//   PURPOSE: Saves instance handle and creates main window
//
//   COMMENTS:
//
//        In this function, we save the instance handle in a global variable and
//        create and display the main program window.
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
   HWND hWnd;

   hInst = hInstance; // Store instance handle in our global variable

   hWnd = CreateWindow(szAppName, szTitle, WS_OVERLAPPEDWINDOW,
      CW_USEDEFAULT, 0, CW_USEDEFAULT, 0,
      NULL, NULL, hInstance, NULL);

   if (!hWnd) {
      return (FALSE);
   }

   ShowWindow(hWnd, nCmdShow);
   UpdateWindow(hWnd);

   return (TRUE);
}

//
//  FUNCTION: WndProc(HWND, unsigned, WORD, LONG)
//
//  PURPOSE:  Processes messages for the main window.
//
//  MESSAGES:
//
// WM_COMMAND - process the application menu
// WM_PAINT - Paint the main window
// WM_DESTROY - post a quit message and return
//    WM_DISPLAYCHANGE - message sent to Plug & Play systems when the display changes
//    WM_RBUTTONDOWN - Right mouse click -- put up context menu here if appropriate
//    WM_NCRBUTTONUP - User has clicked the right button on the application's system menu
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
   int wmId, wmEvent;
   PAINTSTRUCT ps;
   HDC hdc;
      POINT pnt;
   HMENU hMenu;
      BOOL bGotHelp;

   switch (message) {

      case WM_COMMAND:
         wmId    = LOWORD(wParam); // Remember, these are...
         wmEvent = HIWORD(wParam); // ...different for Win32!

         //Parse the menu selections:
         switch (wmId) {

            case IDM_ABOUT:
               DialogBox(hInst, "AboutBox", hWnd, (DLGPROC)About);
               break;

            case IDM_EXIT:
               DestroyWindow (hWnd);
               break;

            case IDM_HELPTOPICS: // Only called in Windows 95
               bGotHelp = WinHelp (hWnd, APPNAME".HLP", HELP_FINDER,(DWORD)0);
               if (!bGotHelp)
               {
                  MessageBox (GetFocus(), GetStringRes(IDS_NO_HELP),
                              szAppName, MB_OK|MB_ICONHAND);
               }
               break;

            case IDM_HELPCONTENTS: // Not called in Windows 95
               bGotHelp = WinHelp (hWnd, APPNAME".HLP", HELP_CONTENTS,(DWORD)0);
               if (!bGotHelp)
               {
                  MessageBox (GetFocus(), GetStringRes(IDS_NO_HELP),
                              szAppName, MB_OK|MB_ICONHAND);
               }
               break;

            case IDM_HELPSEARCH: // Not called in Windows 95
               if (!WinHelp(hWnd, APPNAME".HLP", HELP_PARTIALKEY,
                           (DWORD)(LPSTR)""))
               {
                  MessageBox (GetFocus(), GetStringRes(IDS_NO_HELP),
                              szAppName, MB_OK|MB_ICONHAND);
               }
               break;

            case IDM_HELPHELP: // Not called in Windows 95
               if(!WinHelp(hWnd, (LPSTR)NULL, HELP_HELPONHELP, 0))
               {
                  MessageBox (GetFocus(), GetStringRes(IDS_NO_HELP),
                              szAppName, MB_OK|MB_ICONHAND);
               }
               break;

            // Here are all the other possible menu options,
            // all of these are currently disabled:
            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_LINK:
            case IDM_LINKS:

            default:
               return (DefWindowProc(hWnd, message, wParam, lParam));
         }
         break;

      case WM_NCRBUTTONUP: // RightClick on windows non-client area...
         if (IS_WIN95 && SendMessage(hWnd, WM_NCHITTEST, 0, lParam) == HTSYSMENU)
         {
            // The user has clicked the right button on the applications
            // 'System Menu'. Here is where you would alter the default
            // system menu to reflect your application. Notice how the
            // explorer deals with this. For this app, we aren't doing
            // anything
            return (DefWindowProc(hWnd, message, wParam, lParam));
         } else {
            // Nothing we are interested in, allow default handling...
            return (DefWindowProc(hWnd, message, wParam, lParam));
         }
            break;

        case WM_RBUTTONDOWN: // RightClick in windows client area...
            pnt.x = LOWORD(lParam);
            pnt.y = HIWORD(lParam);
            ClientToScreen(hWnd, (LPPOINT) &pnt);
      // This is where you would determine the appropriate 'context'
      // menu to bring up. Since this app has no real functionality,
      // we will just bring up the 'Help' menu:
            hMenu = GetSubMenu (GetMenu (hWnd), 2);
            if (hMenu) {
                TrackPopupMenu (hMenu, 0, pnt.x, pnt.y, 0, hWnd, NULL);
            } else {
            // Couldn't find the menu...
                MessageBeep(0);
            }
            break;

      case WM_DISPLAYCHANGE: // Only comes through on plug'n'play systems
      {
         SIZE  szScreen;
         DWORD dwBitsPerPixel = (DWORD)wParam;

         szScreen.cx = LOWORD(lParam);
         szScreen.cy = HIWORD(lParam);

         MessageBox (GetFocus(), GetStringRes(IDS_DISPLAYCHANGED),
                     szAppName, 0);
      }
      break;

      case WM_PAINT:
         hdc = BeginPaint (hWnd, &ps);
         // Add any drawing code here...
         EndPaint (hWnd, &ps);
         break;

      case WM_DESTROY:
         // Tell WinHelp we don't need it any more...
               WinHelp (hWnd, APPNAME".HLP", HELP_QUIT,(DWORD)0);
         PostQuitMessage(0);
         break;

      default:
         return (DefWindowProc(hWnd, message, wParam, lParam));
   }
   return (0);
}

//
//  FUNCTION: About(HWND, unsigned, WORD, LONG)
//
//  PURPOSE:  Processes messages for "About" dialog box
//       This version allows greater flexibility over the contents of the 'About' box,
//       by pulling out values from the 'Version' resource.
//
//  MESSAGES:
//
// WM_INITDIALOG - initialize dialog box
// WM_COMMAND    - Input received
//
//
LRESULT CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
   static  HFONT hfontDlg;    // Font for dialog text
   static   HFONT hFinePrint; // Font for 'fine print' in dialog
   DWORD   dwVerInfoSize;     // Size of version information block
   LPSTR   lpVersion;         // String pointer to 'version' text
   DWORD   dwVerHnd=0;        // An 'ignored' parameter, always '0'
   UINT    uVersionLen;
   WORD    wRootLen;
   BOOL    bRetCode;
   int     i;
   char    szFullPath[256];
   char    szResult[256];
   char    szGetName[256];
   DWORD dwVersion;
   char  szVersion[40];
   DWORD dwResult;

   switch (message) {
        case WM_INITDIALOG:
         ShowWindow (hDlg, SW_HIDE);

         if (PRIMARYLANGID(GetUserDefaultLangID()) == LANG_JAPANESE)
         {
            hfontDlg = CreateFont(14, 0, 0, 0, 0, 0, 0, 0, SHIFTJIS_CHARSET, 0, 0, 0,
                                  VARIABLE_PITCH | FF_DONTCARE, "");
            hFinePrint = CreateFont(11, 0, 0, 0, 0, 0, 0, 0, SHIFTJIS_CHARSET, 0, 0, 0,
                                    VARIABLE_PITCH | FF_DONTCARE, "");
         }
         else
         {
            hfontDlg = CreateFont(14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                                  VARIABLE_PITCH | FF_SWISS, "");
            hFinePrint = CreateFont(11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                                    VARIABLE_PITCH | FF_SWISS, "");
         }

         CenterWindow (hDlg, GetWindow (hDlg, GW_OWNER));
         GetModuleFileName (hInst, szFullPath, sizeof(szFullPath));

         // Now lets dive in and pull out the version information:
         dwVerInfoSize = GetFileVersionInfoSize(szFullPath, &dwVerHnd);
         if (dwVerInfoSize) {
            LPSTR   lpstrVffInfo;
            HANDLE  hMem;
            hMem = GlobalAlloc(GMEM_MOVEABLE, dwVerInfoSize);
            lpstrVffInfo  = GlobalLock(hMem);
            GetFileVersionInfo(szFullPath, dwVerHnd, dwVerInfoSize, lpstrVffInfo);
            // The below 'hex' value looks a little confusing, but
            // essentially what it is, is the hexidecimal representation
            // of a couple different values that represent the language
            // and character set that we are wanting string values for.
            // 040904E4 is a very common one, because it means:
            //   US English, Windows MultiLingual characterset
            // Or to pull it all apart:
            // 04------        = SUBLANG_ENGLISH_USA
            // --09----        = LANG_ENGLISH
            // --11----        = LANG_JAPANESE
            // ----04E4 = 1252 = Codepage for Windows:Multilingual

            lstrcpy(szGetName, GetStringRes(IDS_VER_INFO_LANG));

            wRootLen = lstrlen(szGetName); // Save this position

            // Set the title of the dialog:
            lstrcat (szGetName, "ProductName");
            bRetCode = VerQueryValue((LPVOID)lpstrVffInfo,
               (LPSTR)szGetName,
               (LPVOID)&lpVersion,
               (UINT *)&uVersionLen);

            // Notice order of version and string...
            if (PRIMARYLANGID(GetUserDefaultLangID()) == LANG_JAPANESE)
            {
               lstrcpy(szResult, lpVersion);
               lstrcat(szResult, "    o [ W        ");
            }
            else
            {
               lstrcpy(szResult, "About ");
               lstrcat(szResult, lpVersion);
            }

            // -----------------------------------------------------

            SetWindowText (hDlg, szResult);

            // Walk through the dialog items that we want to replace:
            for (i = DLG_VERFIRST; i <= DLG_VERLAST; i++) {
               GetDlgItemText(hDlg, i, szResult, sizeof(szResult));
               szGetName[wRootLen] = (char)0;
               lstrcat (szGetName, szResult);
               uVersionLen   = 0;
               lpVersion     = NULL;
               bRetCode      =  VerQueryValue((LPVOID)lpstrVffInfo,
                  (LPSTR)szGetName,
                  (LPVOID)&lpVersion,
                  (UINT *)&uVersionLen);

               if ( bRetCode && uVersionLen && lpVersion) {
               // Replace dialog item text with version info
                  lstrcpy(szResult, lpVersion);
                  SetDlgItemText(hDlg, i, szResult);
               }
               else
               {
                  dwResult = GetLastError();

                  wsprintf(szResult, GetStringRes(IDS_VERSION_ERROR), dwResult);
                  SetDlgItemText (hDlg, i, szResult);
               }
               SendMessage (GetDlgItem (hDlg, i), WM_SETFONT,
                  (UINT)((i==DLG_VERLAST)?hFinePrint:hfontDlg),
                  TRUE);
            } // for (i = DLG_VERFIRST; i <= DLG_VERLAST; i++)

            GlobalUnlock(hMem);
            GlobalFree(hMem);

         } else {
            // No version information available.
         } // if (dwVerInfoSize)

            SendMessage (GetDlgItem (hDlg, IDC_LABEL), WM_SETFONT,
            (WPARAM)hfontDlg,(LPARAM)TRUE);

         // We are  using GetVersion rather then GetVersionEx
         // because earlier versions of Windows NT and Win32s
         // didn't include GetVersionEx:
         dwVersion = GetVersion();

         if (dwVersion < 0x80000000) {
            // Windows NT
            wsprintf (szVersion, "Microsoft Windows NT %u.%u (Build: %u)",
               (DWORD)(LOBYTE(LOWORD(dwVersion))),
               (DWORD)(HIBYTE(LOWORD(dwVersion))),
                    (DWORD)(HIWORD(dwVersion)) );
         } else if (LOBYTE(LOWORD(dwVersion))<4) {
            // Win32s
                wsprintf (szVersion, "Microsoft Win32s %u.%u (Build: %u)",
               (DWORD)(LOBYTE(LOWORD(dwVersion))),
               (DWORD)(HIBYTE(LOWORD(dwVersion))),
                    (DWORD)(HIWORD(dwVersion) & ~0x8000) );
         } else {
            // Windows 95
                wsprintf (szVersion, "Microsoft Windows 95 %u.%u",
                    (DWORD)(LOBYTE(LOWORD(dwVersion))),
                    (DWORD)(HIBYTE(LOWORD(dwVersion))) );
         }

          SetWindowText (GetDlgItem(hDlg, IDC_OSVERSION), szVersion);
         ShowWindow (hDlg, SW_SHOW);
         return (TRUE);

      case WM_COMMAND:
         if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) {
            EndDialog(hDlg, TRUE);
            DeleteObject (hfontDlg);
            DeleteObject (hFinePrint);
            return (TRUE);
         }
         break;
   }

    return FALSE;
}

//
//   FUNCTION: CenterWindow(HWND, HWND)
//
//   PURPOSE: Centers one window over another.
//
//   COMMENTS:
//
//        In this function, we save the instance handle in a global variable and
//        create and display the main program window.
//
//       This functionwill center one window over another ensuring that
//    the placement of the window is within the 'working area', meaning
//    that it is both within the display limits of the screen, and not
//    obscured by the tray or other framing elements of the desktop.
BOOL CenterWindow (HWND hwndChild, HWND hwndParent)
{
   RECT    rChild, rParent, rWorkArea;
   int     wChild, hChild, wParent, hParent;
   int     xNew, yNew;
   BOOL  bResult;

   // Get the Height and Width of the child window
   GetWindowRect (hwndChild, &rChild);
   wChild = rChild.right - rChild.left;
   hChild = rChild.bottom - rChild.top;

   // Get the Height and Width of the parent window
   GetWindowRect (hwndParent, &rParent);
   wParent = rParent.right - rParent.left;
   hParent = rParent.bottom - rParent.top;

   // Get the limits of the 'workarea'
   bResult = SystemParametersInfo(
      SPI_GETWORKAREA,  // system parameter to query or set
      sizeof(RECT),
      &rWorkArea,
      0);
   if (!bResult) {
      rWorkArea.left = rWorkArea.top = 0;
      rWorkArea.right = GetSystemMetrics(SM_CXSCREEN);
      rWorkArea.bottom = GetSystemMetrics(SM_CYSCREEN);
   }

   // Calculate new X position, then adjust for workarea
   xNew = rParent.left + ((wParent - wChild) /2);
   if (xNew < rWorkArea.left) {
      xNew = rWorkArea.left;
   } else if ((xNew+wChild) > rWorkArea.right) {
      xNew = rWorkArea.right - wChild;
   }

   // Calculate new Y position, then adjust for workarea
   yNew = rParent.top  + ((hParent - hChild) /2);
   if (yNew < rWorkArea.top) {
      yNew = rWorkArea.top;
   } else if ((yNew+hChild) > rWorkArea.bottom) {
      yNew = rWorkArea.bottom - hChild;
   }

   // Set it, and return
   return SetWindowPos (hwndChild, NULL, xNew, yNew, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
}

//---------------------------------------------------------------------------
//
// FUNCTION:    GetStringRes (int id INPUT ONLY)
//
// COMMENTS:    Load the resource string with the ID given, and return a
//              pointer to it.  Notice that the buffer is common memory so
//              the string must be used before this call is made a second time.
//
//---------------------------------------------------------------------------

LPTSTR   GetStringRes (int id)
{
  static TCHAR buffer[MAX_PATH];

  buffer[0]=0;
  LoadString (GetModuleHandle (NULL), id, buffer, MAX_PATH);
  return buffer;
}


GENERIC.H

#define IDM_NEW            100
#define IDM_OPEN           101
#define IDM_SAVE           102
#define IDM_SAVEAS         103
#define IDM_PRINT          104
#define IDM_PRINTSETUP     105
#define IDM_EXIT           106
#define IDM_UNDO           200
#define IDM_CUT            201
#define IDM_COPY           202
//---------------------------------------------------------------------------
//  GENERIC.H
//---------------------------------------------------------------------------

#define IDM_PASTE          203
#define IDM_LINK           204
#define IDM_LINKS          205
#define IDM_HELPCONTENTS   300
#define IDM_HELPSEARCH     301
#define IDM_HELPHELP       302
#define IDM_ABOUT          303
#define IDM_HELPTOPICS     304

#define IDC_STATIC -1

#define DLG_VERFIRST        400
#define IDC_COMPANY        DLG_VERFIRST
#define IDC_FILEDESC          DLG_VERFIRST+1
#define IDC_PRODVER         DLG_VERFIRST+2
#define IDC_COPYRIGHT       DLG_VERFIRST+3
#define IDC_OSVERSION       DLG_VERFIRST+4
#define IDC_TRADEMARK       DLG_VERFIRST+5
#define DLG_VERLAST         DLG_VERFIRST+5

#define IDC_LABEL           DLG_VERLAST+1

#define IDS_APP_TITLE       500
#define IDS_DISPLAYCHANGED  501
#define IDS_VER_INFO_LANG   502
#define IDS_VERSION_ERROR   503
#define IDS_NO_HELP         504


RESOURCE.H

//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by Generic.RC
//

// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NO_MFC                     1
#define _APS_NEXT_RESOURCE_VALUE        101
#define _APS_NEXT_COMMAND_VALUE         40001
#define _APS_NEXT_CONTROL_VALUE         1000
#define _APS_NEXT_SYMED_VALUE           101
#endif
#endif


README.TXT

Minimum Console Application

The SIMPLE sample is a minimum console application. It's a Win32 version of
the classic 'Hello, World' C program.


SIMPLE.C

/******************************************************************************\
*       This is a part of the Microsoft Source Code Samples.
*       Copyright 1993 - 1998 Microsoft Corporation.
*       All rights reserved.
*       This source code is only intended as a supplement to
*       Microsoft Development Tools and/or WinHelp documentation.
*       See these sources for detailed information regarding the
*       Microsoft samples programs.
\******************************************************************************/

#include <stdio.h>

main()

{
#ifdef JAPAN
        printf (" v     R Q A             I");
#else
        printf ("Win32, it's happenin'!");
#endif

        return(0);
}