home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 22 gnu
/
22-gnu.zip
/
spmio10.zip
/
gcc2
/
stdwin
/
stdwin.cc
< prev
next >
Wrap
C/C++ Source or Header
|
1994-08-28
|
12KB
|
396 lines
#include <stdio.h>
#include <stdlib.h>
#include "stdwin.h"
#ifdef NDEBUG
#define LOG(format, args...)
#else
FILE *logfile;
#define LOG(format, args...) \
fprintf (logfile, "%s:%d: " format "\n", __FILE__, __LINE__ , ##args )
#endif
/* The purpose of this class is to provide a scope whose members all
* have friend priveledges with respect to class StdWin
*/
class StdWinUtils
{
public:
static MRESULT ClientWindowProcedure (HWND, unsigned long, MPARAM, MPARAM);
};
/* The Name of the PM class created to deal with std windows */
const char * const classname = "FreeStandardWindow";
/* get_hab -- get the HAB handle for the program. If the user mislinks
* his application, this call will fail. On the bright side, if he mislinks
* his app, stdio probably works, so we can issue a diagnostic.
*/
static HAB get_hab ()
{
HAB hab = WinInitialize (0);
#ifndef NDEBUG
logfile = fopen ("log", "wt");
setbuf (logfile, 0);
#endif
LOG ("In get_hab");
if (hab == 0)
{
fprintf (stderr,
"WinInitialize failed. Did you forget to put WINDOWAPI in "
"your linker\n definition file?");
exit (1);
}
/* Register the client class for StdWin before any windows are created */
WinRegisterClass (hab, classname, StdWinUtils::ClientWindowProcedure,
CS_SIZEREDRAW, sizeof (void *));
return hab;
}
/* get_hab -- get the HAB handle for the program. Another opportunity
* to make fun of the user who mislinks his application.
*/
static HMQ get_hmq ()
{
HMQ hmq = WinCreateMsgQueue (StdWin::hab, 0);
if (hmq == 0)
{
fprintf (stderr,
"WinCreateMsgQueue failed. Did you forget to put WINDOWAPI in "
"your linker\n definition file?");
exit (1);
}
LOG ("finished get_hmq");
return hmq;
}
/* Class static data - HAB and HMQ handles */
HAB StdWin::hab = get_hab ();
HMQ StdWin::hmq = get_hmq ();
/* Phony Object to effect the destruction of the hab and hmq when the
* program exits */
class Destroyer
{
public:
~Destroyer ();
};
static Destroyer destroyer;
Destroyer::~Destroyer ()
{
WinDestroyMsgQueue(StdWin::hmq);
WinTerminate(StdWin::hab);
}
/* Variable used for communicating the window being created between
* StdWin::activate_window and ClientWindowProcedure. Note that this
* only works if we have only one thread of execution. To improve this,
* we need to avoid WinCreateStdWindow and create the window the hard way.
* But that would be harder to read and understand. */
static StdWin *activating_window = 0;
/* ClientWindowProcedure -- the function that accepts all PM messages
* on behalf of all instances of StdWin. This function will find the
* appropriate StdWin instance that the client window belongs to
* and pass the message on to the instance's own message handler.
*/
MRESULT StdWinUtils::ClientWindowProcedure (HWND win, unsigned long msg,
MPARAM mp1, MPARAM mp2)
{
StdWin *window_object;
if (msg == WM_CREATE && activating_window != 0)
{
window_object = activating_window;
activating_window = 0;
WinSetWindowPtr (win, 0, window_object);
}
else
window_object = (StdWin *) WinQueryWindowPtr (win, 0);
if (window_object != 0)
return window_object->message (win, msg, mp1, mp2);
// Punt
LOG ("Punting message");
return WinDefWindowProc (win, msg, mp1, mp2);
}
/* Stdwin object constructor.
* The default frame style is a frame with everything except those items
* which require a resource file
*/
StdWin::StdWin ()
: window (0),
style_flags (FCF_SYSMENU | FCF_TASKLIST | FCF_SIZEBORDER | FCF_TITLEBAR
| FCF_MINMAX | FCF_SHELLPOSITION),
resource_id (0),
window_is_active (0)
{
}
/* Stdwin object destructor */
StdWin::~StdWin ()
{
// Destroy the window if the user left it active.
destroy_window ();
}
/* Functions to change the frame options. These must be called before
* the window is activated.
* Does anyone think this would be more readable and easier to maintain
* without these macros?
*/
#define ENABLE(item, bit) \
void StdWin::enable_##item() \
{ \
style_flags |= FCF_##bit; \
} \
void StdWin::disable_##item() \
{ \
style_flags &= ~ (FCF_##bit); \
}
ENABLE (acceltable, ACCELTABLE);
ENABLE (icon, ICON);
ENABLE (maxbutton, MAXBUTTON);
ENABLE (menu, MENU);
ENABLE (minbutton, MINBUTTON);
ENABLE (minmax, MINMAX);
ENABLE (shellposition, SHELLPOSITION);
ENABLE (sizeborder, SIZEBORDER);
ENABLE (sysmenu, SYSMENU);
ENABLE (tasklist, TASKLIST);
ENABLE (titlebar, TITLEBAR);
/* The function that causes a PM window to be created that is controlled
* by this StdWin instance.
*/
void StdWin::activate_window ()
{
HWND foo;
activating_window = this;
window_is_active = 1;
WinCreateStdWindow (HWND_DESKTOP, WS_VISIBLE, &style_flags,
classname, 0, 0, 0, resource_id, &foo);
}
/* A function to shutdown/remove the PM window controlled by this StdWin
* instance */
void StdWin::destroy_window ()
{
if (window_is_active)
WinDestroyWindow(frame);
window_is_active = 0;
}
/* A member function that accepts all PM messages directed at the PM window
* controlled by this StdWin instance.
* The default behavior of this handler is to decode the mp1 and mp2
* message arguments and send the message on to a message-specific virtual
* member function for further processing.
*/
MRESULT StdWin::message (HWND win, unsigned amsg, MPARAM amp1, MPARAM amp2)
{
unsigned save_msg = amsg;
MPARAM save_mp1 = mp1;
MPARAM save_mp2 = mp2;
window = win;
msg = amsg;
mp1 = amp1;
mp2 = amp2;
MRESULT ret;
switch (msg)
{
case WM_CREATE:
// Init the instance's frame window handle
frame = WinQueryWindow (win, QW_PARENT);
ret = msg_create ();
break;
case WM_ACTIVATE:
ret = msg_activate (SHORT1FROMMP (mp1), (HWND) mp2);
break;
case WM_ADJUSTWINDOWPOS:
ret = msg_adjustwindowpos ((SWP *) mp1);
break;
case WM_CHAR:
ret = msg_char (SHORT1FROMMP (mp1), CHAR3FROMMP (mp1), CHAR4FROMMP (mp1),
SHORT1FROMMP (mp2), SHORT2FROMMP (mp2));
break;
case WM_CLOSE:
ret = msg_close ();
break;
case WM_CONTROLPOINTER:
ret = msg_controlpointer (SHORT1FROMMP (mp1), (HPOINTER) mp2);
break;
case WM_DESTROY:
ret = msg_destroy ();
break;
case WM_ERASEBACKGROUND:
ret = msg_erasebackground ((HPS) mp1, (RECTL *) mp2);
break;
case WM_FOCUSCHANGE:
ret = msg_focuschange ((HWND) mp1,
SHORT1FROMMP (mp2), SHORT2FROMMP (mp2));
break;
case WM_FORMATFRAME:
ret = msg_formatframe ((SWP *) mp1, (RECTL *) mp2);
break;
case WM_MOUSEMOVE:
ret = msg_mousemove (SHORT1FROMMP (mp1), SHORT2FROMMP (mp1),
SHORT1FROMMP (mp2), SHORT2FROMMP (mp2));
break;
case WM_PAINT:
ret = msg_paint ();
break;
case WM_REALIZEPALETTE:
ret = msg_realizepalette ();
break;
case WM_SAVEAPPLICATION:
ret = msg_saveapplication ();
break;
case WM_SETFOCUS:
ret = msg_setfocus ((HWND) mp1, SHORT1FROMMP (mp2));
break;
case WM_SETSELECTION:
ret = msg_setselection (SHORT1FROMMP (mp1));
break;
case WM_SHOW:
ret = msg_show (SHORT1FROMMP (mp1));
break;
case WM_SIZE:
ret = msg_size (SHORT1FROMMP (mp1), SHORT2FROMMP (mp1),
SHORT1FROMMP (mp2), SHORT2FROMMP (mp2));
break;
case WM_WINDOWPOSCHANGED:
ret = msg_windowposchanged ((SWP *) mp1, (unsigned) mp2);
break;
case WM_USER+1:
ret = msg_user1 (mp1, mp2);
break;
case WM_USER+2:
ret = msg_user2 (mp1, mp2);
break;
case WM_USER+3:
ret = msg_user3 (mp1, mp2);
break;
case WM_USER+4:
ret = msg_user4 (mp1, mp2);
break;
default:
LOG ("Undecoded message: 0x%04X", msg);
ret = default_message ();
break;
// The following messages need work. I have not yet decoded the
// arguments for these functions...
case WM_QUERYFOCUSCHAIN:
ret = msg_queryfocuschain ();
break;
case WM_QUERYDLGCODE:
ret = msg_querydlgcode ();
break;
}
msg = save_msg;
mp1 = save_mp1;
mp2 = save_mp2;
return ret;
}
/* Send functions for sending messages to the HWND controlled by the
* StdWin object.
*/
MRESULT StdWin::send_msg (unsigned amsg, MPARAM amp1, MPARAM amp2)
{
return WinSendMsg (window, amsg, amp1, amp2);
}
MRESULT StdWin::send_close ()
{
return send_msg (WM_CLOSE, 0, 0);
}
MRESULT StdWin::send_user1 (MPARAM mp1, MPARAM mp2)
{
return send_msg (WM_USER + 1, mp1, mp2);
}
MRESULT StdWin::send_user2 (MPARAM mp1, MPARAM mp2)
{
return send_msg (WM_USER + 2, mp1, mp2);
}
MRESULT StdWin::send_user3 (MPARAM mp1, MPARAM mp2)
{
return send_msg (WM_USER + 3, mp1, mp2);
}
MRESULT StdWin::send_user4 (MPARAM mp1, MPARAM mp2)
{
return send_msg (WM_USER + 4, mp1, mp2);
}
/* A handler for messages that we want to default to the behavior of
* the default PM message handler.
* Note that we have squirreled away the actual mp1 and mp2 arguments in the
* function StdWin::message. We do this for two reasons: First, this
* way we don't have to re-encode the arguments back into the mp1 and mp2
* types. Second, if any of the fields of mp1 and mp2 that are
* RESERVED in the PM documentation are actually used by PM, the squirelled
* values of mp1 and mp2 will preserve the contents of the reserved fields.
*/
MRESULT StdWin::default_message ()
{
return WinDefWindowProc (window, msg, mp1, mp2);
}
/* For every message type that we have created virtual member functions for,
* we write a default method that simply causes the default window procedure
* to be invoked.
*/
#define DEFAULT(msg) \
MRESULT StdWin::msg \
{ \
LOG(#msg " sent to base class"); \
return default_message (); \
}
DEFAULT (msg_create ());
DEFAULT (msg_paint ());
DEFAULT (msg_activate (int, HWND));
DEFAULT (msg_adjustwindowpos (SWP *));
DEFAULT (msg_char (unsigned short, unsigned char, unsigned char,
unsigned short, unsigned short));
DEFAULT (msg_close ());
DEFAULT (msg_controlpointer (unsigned short, HPOINTER));
DEFAULT (msg_destroy ());
DEFAULT (msg_erasebackground (HPS, RECTL *));
DEFAULT (msg_focuschange (HWND, unsigned short, unsigned short));
DEFAULT (msg_formatframe (SWP *, RECTL *));
DEFAULT (msg_mousemove (short, short, unsigned short, unsigned short));
DEFAULT (msg_realizepalette ());
DEFAULT (msg_saveapplication ());
DEFAULT (msg_setfocus (HWND, unsigned short));
DEFAULT (msg_setselection (unsigned short));
DEFAULT (msg_show (unsigned short));
DEFAULT (msg_size (short, short, short, short));
DEFAULT (msg_windowposchanged (SWP *, unsigned));
DEFAULT (msg_user1 (MPARAM, MPARAM));
DEFAULT (msg_user2 (MPARAM, MPARAM));
DEFAULT (msg_user3 (MPARAM, MPARAM));
DEFAULT (msg_user4 (MPARAM, MPARAM));
// Functions that need work
DEFAULT (msg_querydlgcode ());
DEFAULT (msg_queryfocuschain ());
/* Standard message dispatch loop */
void StdWin::StdMessageLoop ()
{
QMSG qmsg;
while (WinGetMsg(hab, &qmsg, 0, 0, 0))
WinDispatchMsg(hab, &qmsg);
}