home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 10 Tools
/
10-Tools.zip
/
wclass.zip
/
CLASSLIB.CPP
< prev
next >
Wrap
Text File
|
1994-04-25
|
15KB
|
527 lines
/*----------------------------------------------------------------------------*/
/* (c) 1993, 1994 Larry Morley / Enlightened Computer Solutions */
/*----------------------------------------------------------------------------*/
/* module: classlib.cpp created_on: 1 May 1993 by: LJM */
/* desc : Main framework class lib source file */
/* complr: icc /Fi /Fd /c /Ss /Sp1 /Gm+ /G4 /Kb+ [/Ti+ intrnl, /Ti- rel] */
/* lnkr : link386 /a:4 [/deb intrnl,rel=<none> /base:65536 /noe */
/* rc $*.res */
/* etc : rc -r $*.rc */
/* mkfile: makefile */
/* depend: (see makefile) */
/* mhist : LJM 02 May 1993 Added functionality to Menu class */
/*----------------------------------------------------------------------------*/
#define INCL_WIN
#define INCL_DOS
#define INCL_GPI
#include <os2.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "cppapp.hpp"
#include "classlib.hpp"
/*----------------------------------------------------------------------------*/
// Class names
CHAR szClientClass[] = "C++ClientWindow";
CHAR szFrameClass[] = "C++FrameWindow";
CHAR szStatLineClass[] = "C++StatusWindow";
CHAR szStatLineText[256];
// Standard style flags
ULONG ulFrameFlags = FCF_TITLEBAR | FCF_SYSMENU |
FCF_SIZEBORDER | FCF_MINMAX |
FCF_SHELLPOSITION | FCF_TASKLIST |
FCF_MENU | FCF_ICON ;
HAB hab;
HMQ hmq;
QMSG qmsg;
PFNWP pfnOrigFrameProc;
USHORT cbFrameExtra;
/*----------------------------------------------------------------------------*/
// These are all pretty straightforward -
// start by creating an App,
// create windows or whatever else is needed,
// and run the App (App->Run()).
// Sets up the message queue
App :: App()
{
hab = WinInitialize((USHORT)0);
hmq = WinCreateMsgQueue(hab,(SHORT)0);
}
/*----------------------------------------------------------------------------*/
// The message loop
void App :: Run()
{
while (WinGetMsg(hab,&qmsg,(HWND)0,(USHORT)0,(USHORT)0))
WinDispatchMsg(hab,&qmsg);
}
/*----------------------------------------------------------------------------*/
// Cleanup
App :: ~App()
{
WinDestroyMsgQueue(hmq);
WinTerminate(hab);
}
/*----------------------------------------------------------------------------*/
// Cleanup
Window :: ~Window()
{
WinDestroyWindow(hwndFrame);
}
/*----------------------------------------------------------------------------*/
// These methods all apply to the hwndMenu member of the window -
// I won't describe them in detail, since they're pretty much
// straightforward.
void Menu :: DisableItem(Window *pWindow,USHORT idItem)
{
WinSendMsg(
pWindow->hwndMenu,
MM_SETITEMATTR,
MPFROM2SHORT(
idItem,
TRUE),
MPFROM2SHORT(
MIA_DISABLED,
MIA_DISABLED));
}
/*----------------------------------------------------------------------------*/
void Menu :: EnableItem(Window *pWindow,USHORT idItem)
{
WinSendMsg(
pWindow->hwndMenu,
MM_SETITEMATTR,
MPFROM2SHORT(
idItem,
TRUE),
MPFROM2SHORT(
MIA_DISABLED,
FALSE));
}
/*----------------------------------------------------------------------------*/
void Menu :: CheckItem(Window *pWindow,USHORT idItem)
{
WinSendMsg(
pWindow->hwndMenu,
MM_SETITEMATTR,
MPFROM2SHORT(
idItem,
TRUE),
MPFROM2SHORT(
MIA_CHECKED,
MIA_CHECKED));
}
/*----------------------------------------------------------------------------*/
void Menu :: UnCheckItem(Window *pWindow,USHORT idItem)
{
WinSendMsg(
pWindow->hwndMenu,
MM_SETITEMATTR,
MPFROM2SHORT(
idItem,
TRUE),
MPFROM2SHORT(
MIA_CHECKED,
FALSE));
}
/*----------------------------------------------------------------------------*/
// Create a frame window with a status bar / message bar at the bottom
BOOL Window :: Create()
{
// Take an existing class (WC_FRAME), get its
// window proc, add extra room (window words)
// and re-register it under my own classname.
CLASSINFO ci;
WinQueryClassInfo(hab,WC_FRAME,&ci);
pfnOrigFrameProc = ci.pfnWindowProc;
cbFrameExtra = ci.cbWindowData;
// Try to re-register; return FALSE if
// attempt fails
if (!WinRegisterClass(
hab,
szFrameClass,
FrameWndProc,
ci.flClassStyle & (~CS_PUBLIC),
ci.cbWindowData+sizeof(this)))
return FALSE;
// Register the client window class
// (I should probably check here)
WinRegisterClass(
hab,
szClientClass,
ClientWndProc,
CS_SIZEREDRAW,
sizeof(this));
// Register the status window class
// (should probably check here too)
WinRegisterClass(
hab,
szStatLineClass,
StatLineWndProc,
CS_SIZEREDRAW,
sizeof(this));
// Start creating windows: I don't use WinCreateStdWindow(),
// create each piece individually. That gives me the
// flexibility of being able to put a pointer to "this" in
// the components of the window.
// To do it this way, start with the frame:
hwndFrame = WinCreateWindow(
HWND_DESKTOP, /* parent */
szFrameClass, /* class */
"Main Window", /* title */
0L, /* style */
0, /* x */
0, /* y */
0, /* cx */
0, /* cy */
(HWND)0, /* owner */
HWND_TOP, /* z-order */
ID_RESOURCE, /* window id */
this, /* control parms */
(PVOID)0); /* pres parms */
if (!hwndFrame)
return FALSE;
// Then, create the client with an id
// of FID_CLIENT (very important)
hwndClient = WinCreateWindow(
hwndFrame,
szClientClass,
(PSZ)0,
0L,
0,
0,
0,
0,
hwndFrame,
HWND_TOP,
FID_CLIENT,
(PVOID)this,
(PVOID)0);
if (!hwndClient)
return FALSE;
// And lastly, I create the status
// bar window
hwndStatus = WinCreateWindow(
hwndFrame,
szStatLineClass,
(PSZ)0,
0L,
0,
0,
0,
0,
hwndFrame,
HWND_TOP,
FID_STATUS,
(PVOID)this,
(PVOID)0);
if (!hwndStatus)
return FALSE;
// Set the window's text and show it
WinSetWindowText(hwndFrame,"C++ PM Application by Larry Morley");
WinShowWindow(hwndFrame,TRUE);
return TRUE;
}
/*----------------------------------------------------------------------------*/
// Event handler for WM_PAINT
MRESULT Window :: PaintEventHandler(HWND hwnd,ULONG msg,MPARAM mp1,MPARAM mp2)
{
HPS hPS;
RECTL rcl;
hPS = WinBeginPaint(hwnd,(HPS)0,&rcl);
GpiErase(hPS);
WinEndPaint(hPS);
return (MRESULT)0;
}
/*----------------------------------------------------------------------------*/
// Event handler for WM_MENUSELECT
MRESULT Window :: MenuSelectEventHandler
(HWND hwnd,ULONG msg,MPARAM mp1,MPARAM mp2)
{
return WinDefWindowProc(hwnd,msg,mp1,mp2);
}
/*----------------------------------------------------------------------------*/
// Event handler for WM_COMMAND (mostly for menu)
MRESULT Window :: CommandEventHandler(HWND hwnd,ULONG msg,MPARAM mp1,MPARAM mp2)
{
return WinDefWindowProc(hwnd,msg,mp1,mp2);
}
/*----------------------------------------------------------------------------*/
// This is how I make room for the status bar window at the bottom, and
// actually make it an integral part of the frame.
MRESULT Window :: FormatFrameEventHandler
(HWND hwnd,ULONG msg,MPARAM mp1,MPARAM mp2)
{
int origCount;
// The original proc returns the number of items in the frame window
origCount = (int)((*pfnOrigFrameProc)(hwnd,msg,mp1,mp2));
// Enumerate them and look for FID_CLIENT
if (origCount)
{
int i;
for (i=0;i<origCount;i++)
{
if (WinQueryWindowUShort(((PSWP)mp1)[i].hwnd,QWS_ID)
== FID_CLIENT)
{
HWND hwndTemp;
// Position the status / message / whatever bar
hwndTemp=WinWindowFromID(hwnd,FID_STATUS);
if (hwndTemp)
WinSetWindowPos(hwndTemp,
HWND_TOP,
((PSWP)mp1)[i].x,
((PSWP)mp1)[i].y,
((PSWP)mp1)[i].cx,
25,
((PSWP)mp1)[i].fl);
// And adjust the size of the client
// area accordingly (it's fixed at 25
// right now; you could base it on
// pretty much anything you wish)
((PSWP)mp1)[i].y += 25;
((PSWP)mp1)[i].cy -= 25;
}
}
}
// Tell PM how many parts are in the frame
return (MRESULT)origCount;
}
/*----------------------------------------------------------------------------*/
MRESULT EXPENTRY ClientWndProc(HWND hwnd,ULONG msg,MPARAM mp1,MPARAM mp2)
{
Window *w;
MRESULT rc;
// See if the window contains a pointer to
// a Window object.
w = (Window *)WinQueryWindowPtr(hwnd,0);
switch (msg)
{
// WM_CREATE is called directly, not sent; when you
// call WinCreateWindow() the function calls the window
// proc with WM_CREATE. That's why it's safe to set
// the pointer to the owner object here - I'm guaranteed
// that nothing else will happen in the meantime.
case WM_CREATE:
WinSetWindowPtr(hwnd,0,(PVOID)mp1);
((Window *)mp1)->hwndMenu =
WinWindowFromID(
WinQueryWindow(hwnd,QW_PARENT),FID_MENU);
break;
// The rest of the code just dispatches messages
// to the appropriate event handlers.
case WM_PAINT:
rc = w->PaintEventHandler(hwnd,msg,mp1,mp2);
return rc;
case WM_COMMAND:
rc = w->CommandEventHandler(hwnd,msg,mp1,mp2);
return rc;
case WM_MENUSELECT:
rc = w->MenuSelectEventHandler(hwnd,msg,mp1,mp2);
return rc;
}
return WinDefWindowProc(hwnd,msg,mp1,mp2);
}
/*----------------------------------------------------------------------------*/
// This is my "replacement" frame window procedure -
// I get the information I want, then pass the rest along
// to the default procedure. It's also where I catch the
// WM_FORMATFRAME message.
MRESULT EXPENTRY FrameWndProc(HWND hwnd,ULONG msg,MPARAM mp1,MPARAM mp2)
{
switch (msg)
{
case WM_CREATE:
// mp1 is a pointer to "this" -
// set it up here for the same
// reasons as for the client window.
WinSetWindowPtr(hwnd,cbFrameExtra,(PVOID)mp1);
// Alter the frame data that I want
// to change...
FRAMECDATA fcdata;
fcdata.cb = sizeof(fcdata);
fcdata.flCreateFlags = ulFrameFlags;
fcdata.hmodResources = (HMODULE)0L;
fcdata.idResources = ID_RESOURCE;
return (*pfnOrigFrameProc)(hwnd,msg,(MPARAM)&fcdata,mp2);
case WM_FORMATFRAME:
// Invoke Window::FormatFrameEventHandler()
Window *w;
MRESULT rc;
w = (Window *)WinQueryWindowPtr(hwnd,cbFrameExtra);
rc = w->FormatFrameEventHandler(hwnd,msg,mp1,mp2);
return rc;
case WM_MENUSELECT:
// This case is nescessary in the frame window proc
// because that's where the system menu MENUSELECTS
// are sent.
w = (Window *)WinQueryWindowPtr(hwnd,cbFrameExtra);
rc = w->MenuSelectEventHandler(hwnd,msg,mp1,mp2);
return rc;
default:
break;
}
// Can't use WinDefWindowProc(); have to use the default
// WC_FRAME window proc.
return (*pfnOrigFrameProc)(hwnd,msg,mp1,mp2);
}
/*----------------------------------------------------------------------------*/
// This is a pretty straightforward window procedure; it's the window proc
// for the status / message / whatever area.
MRESULT EXPENTRY StatLineWndProc(HWND hwnd,ULONG msg,MPARAM mp1,MPARAM mp2)
{
HPS hPS;
RECTL rcl;
POINTL ptl;
LONG lColor;
static SHORT cxClient;
static SHORT cyClient;
static int cyChar;
static int cyDesc;
static int cxChar;
static int cxCaps;
switch (msg)
{
case WM_CREATE:
FONTMETRICS fm;
hPS = WinGetPS(hwnd);
GpiQueryFontMetrics(hPS,(LONG)sizeof(fm),&fm);
cyChar = (int)fm.lMaxBaselineExt;
cyDesc = (int)fm.lMaxDescender;
cxChar = (int)fm.lEmInc;
cxCaps = (int)fm.lAveCharWidth;
WinReleasePS(hPS);
strcpy(szStatLineText,"Ready.");
break;
case WM_SIZE:
cxClient = SHORT1FROMMP(mp2);
cyClient = SHORT2FROMMP(mp2);
break;
case WM_PAINT:
hPS = WinBeginPaint(hwnd,(HPS)0,&rcl);
WinFillRect(hPS,&rcl,CLR_PALEGRAY);
lColor = GpiQueryColor(hPS);
GpiSetColor(hPS,CLR_DARKGRAY);
ptl.x = 0;
ptl.y = cyClient-1;
GpiMove(hPS,&ptl);
ptl.x = cxClient-1;
ptl.y = cyClient-1;
GpiLine(hPS,&ptl);
ptl.x = cxClient-1;
ptl.y = 0;
GpiLine(hPS,&ptl);
GpiSetColor(hPS,lColor);
ptl.x = 2;
ptl.y = cyClient-cyChar-1;
GpiCharStringAt(hPS,&ptl,strlen(szStatLineText),szStatLineText);
WinEndPaint(hPS);
break;
default:
return WinDefWindowProc(hwnd,msg,mp1,mp2);
}
return (MRESULT)0L;
}
/*----------------------------------------------------------------------------*/