|
|
Microsoft OS/2 SDK 2.0 05-30-1990
/*==============================================================*\
* img_main.c - Image Porting PM application main source file
* Created 1989, 1990 IBM, Microsoft Corp.
*--------------------------------------------------------------
*
* This application serves as an example of porting a 16-bit
* application to 32-bit. It takes a 16-bit application which
* can be built using the headers/libraries/tools from an OS/2 1.2
* toolkit and ends up with a pure 32-bit application.
*
*--------------------------------------------------------------
*
* This source file contains the following functions:
*
* main()
* MainWndProc(hwnd, msg, mp1, mp2)
* FrameWndProc(hwnd, msg, mp1, mp2)
* MessageBox(hwnd idMsg, fsStyle, fBeep)
* MainCommand(mp1, mp2)
* ExitProc(usTermCode)
*
\*==============================================================*/
/*--------------------------------------------------------------*\
* Include files, macros, defined constants, and externs *
\*--------------------------------------------------------------*/
#define INCL_DOSPROCESS
#define INCL_WINWINDOWMGR
#define INCL_WINFRAMEMGR
#define INCL_WINSYS
#define INCL_WINTRACKRECT
#define INCL_WINHELP
#define INCL_GPIPRIMITIVES
/*--------------------------------------------------------------*\
* Include files, macros, defined constants, and externs *
\*--------------------------------------------------------------*/
#include <os2.h>
#include <string.h>
#include "img_main.h"
#include "img_xtrn.h"
#include "img_help.h"
/*--------------------------------------------------------------*\
* error defines *
\*--------------------------------------------------------------*/
#define RETURN_SUCCESS 0 /* successful return in DosExit */
#define RETURN_ERROR 1 /* error return in DosExit */
#define BEEP_WARN_FREQ 60 /* frequency of warning beep */
#define BEEP_WARN_DUR 100 /* duration of warning beep */
/*--------------------------------------------------------------*\
* Entry point declarations *
\*--------------------------------------------------------------*/
VOID MainCommand(MPARAM mp1, MPARAM mp2);
/*--------------------------------------------------------------*\
* Static variables *
\*--------------------------------------------------------------*/
HMQ hmq; /* application queue handle */
/****************************************************************\
* Main routine *
*--------------------------------------------------------------*
* *
* Name: main() *
* *
* Purpose: Initializes the PM environment, calls the *
* initialization routine, creates the main *
* window, and polls the message queue *
* *
* Usage: *
* *
* Method: *
* - obtains anchor block handle and creates message *
* queue *
* - calls the initialization routine *
* - creates the main frame window which creates the *
* main client window *
* - polls the message queue via Get/Dispatch Msg loop *
* - upon exiting the loop, exits *
* *
* Returns: *
* 1 - if sucessful execution completed *
* 0 - if error *
\****************************************************************/
BOOL cdecl main(VOID)
{
QMSG qmsg; /* message structure */
USHORT rc;
vhab = WinInitialize(0);
if(!vhab) {
DosBeep(BEEP_WARN_FREQ, BEEP_WARN_DUR);
return RETURN_ERROR;
}
/* find a define for this v */
hmq = WinCreateMsgQueue(vhab, 0);
if(!hmq) {
DosBeep(BEEP_WARN_FREQ, BEEP_WARN_DUR);
WinTerminate(vhab);
return RETURN_ERROR;
}
if(rc = Init()) {
MessageBox(HWND_DESKTOP, rc, 0, MB_OK | MB_ERROR, TRUE);
} else {
/* get/dispatch message loop */
while (WinGetMsg(vhab, &qmsg, (HWND)NULL, 0, 0))
WinDispatchMsg(vhab, &qmsg);
}
/*
* release any allocated resource - no need to check return codes
*/
#ifdef HELP_MANAGER_ENABLED
/* destroy the help instance */
HelpDestroyInstance();
#endif
return RETURN_SUCCESS;
} /* main() */
/****************************************************************\
* Main client window procedure *
*--------------------------------------------------------------*
* *
* Name: MainWndProc(hwnd, msg, mp1, mp2) *
* *
* Purpose: Processes the messages sent to the main client *
* window. This routine processes the basic *
* messages all client windows should process *
* and passes all others onto UserWndProc where *
* the developer can process any others. *
* *
* Usage: Called for each message placed in the main *
* window's message queue *
* *
* Method: a switch statement branches to the routines to be *
* performed for each message processed. Any messages *
* not specifically process are passed to the user's *
* message processing procedure UserWndProc(). *
* *
* Returns: Return values are determined by each message *
* *
\****************************************************************/
MRESULT EXPENTRY MainWndProc(hwnd, msg, mp1, mp2)
HWND hwnd; /* handle of window */
USHORT msg; /* id of message */
MPARAM mp1; /* first message parameter */
MPARAM mp2; /* second message parameter */
{
PSWP pswp;
BOOL fHScroll;
RECTL rcl;
POINTL ptl;
switch (msg) {
case WM_CREATE:
/*
* set application title to 'Untitled'
*/
UtilUpdateTitleText(vhab,
((PCREATESTRUCT)PVOIDFROMMP(mp2))->hwndParent,
"");
/* return FALSE to continue window creation, TRUE to abort it */
return (MRESULT)FALSE;
break;
case WM_INITMENU:
/*
* disable/enable menu items as appropriate
*/
MenuInit(mp1, mp2);
break;
case WM_ERASEBACKGROUND:
/*
* The client window is cleared to SYSCLR_WINDOW
*/
return (MRESULT)TRUE;
break;
case WM_MINMAXFRAME:
/*
* the window can be maximized by double clicking on the
* title bar, clicking on the maximize icon, or by
* selecting the maximize option in the System Menu.
* The SizeCalculateMaxWindow() function is invoked to set the
* window to a size that is no larger than the loaded image.
*/
pswp = (PSWP)mp1;
#if (defined(PORT_S132) || defined(PORT_32))
if (pswp->fl & SWP_MAXIMIZE) {
#else
if (pswp->fs & SWP_MAXIMIZE) {
#endif
/*
* disable options which aren't valid when
* the window is maximized
*/
vfMaximized = TRUE;
if (vfDetail) {
SizeCalculateMaxWindow(&rcl);
pswp->cy = (SHORT)(rcl.yTop - rcl.yBottom);
pswp->cx = (SHORT)(rcl.xRight - rcl.xLeft);
pswp->y = (SHORT)rcl.yBottom;
pswp->x = (SHORT)rcl.xLeft;
}
} else
/*
* re-enable options which were invalid when
* the window was maximized
*/
vfMaximized = FALSE;
break;
case WM_PAINT:
WinBeginPaint(hwnd, vhps, (PRECTL)&rcl);
if (vfImgLoaded && vfDetail)
/*
* If an image has been loaded and the user has selected
* the 'Detail' view, the PaintUnSizedImage() function is
* invoked to draw the image data in the client window.
* The image is drawn unscaled, and clipped if necessary.
*/
PaintUnSizedImage();
else if (vfImgLoaded && !vfDetail)
/*
* If an image has been loaded and the user has selected
* the 'Non-detailed' view, the PaintSizedImage() function is
* invoked to size the image and draw it. * The image is drawn scaled to fit the window.
*/
PaintSizedImage();
else
/*
* If no image data has been loaded, clear the window to
* the default system color. */
WinFillRect(vhps, &rcl, SYSCLR_WINDOW);
WinEndPaint(vhps);
break;
case WM_SIZE:
/*
* If the window size is altered and the image is being
* viewed in detail, the WndSize function is invoked to restrict
* the new window size and scroll-bar range to image limits.
* If the 'Non-detailed' view has been selected and the window
* size is altered, the image has to be redrawn to fit the window.
*/
if (vfImgLoaded && vfDetail)
SizePositionImage(mp2);
WinInvalidateRect(hwnd, (PRECTL)NULL, FALSE);
break;
case WM_HSCROLL:
case WM_VSCROLL:
/*
* scrolling is implemented only if an image has been
* loaded, the 'Detail' view has been selected, and there is
* image data still lying outside window limits.
*/
fHScroll = (BOOL)(msg == WM_HSCROLL);
if (vfImgLoaded && vfDetail &&
(fHScroll ? vulScrollXMax > 0 : vulScrollYMax > 0)) {
GpiQueryCurrentPosition(vhps, &ptl);
WinQueryWindowRect(hwnd, &rcl);
/* call the appropriate scroll routine */
(fHScroll ? SizeHScroll(mp2, rcl, ptl) :
SizeVScroll(mp2, rcl, ptl));
}
break;
case WM_DESTROY:
/*
* delete the image graphics presentation space
*/
GpiAssociate(vhps, (HDC)NULL);
GpiDestroyPS(vhps);
if (vfImgLoaded) {
/*
* Free any allocated memory
*/
#if (defined(PORT_16) || defined(PORT_S132))
UtilMemoryFree(SELECTOROF(vpbImgBuf));
#else
UtilMemoryFree(vpbImgBuf);
#endif
/*
* Release all bit-map resources and close the memory
* device context
*/
GpiSetBitmap(vhpsMem, (HBITMAP)NULL);
GpiDeleteBitmap(vhbm);
GpiAssociate(vhpsMem, (HDC)NULL);
GpiDestroyPS(vhpsMem);
DevCloseDC(vhdcMem);
}
/*
* ensure that the scroll bars are child windows of the
* frame, so that they will be destroyed automatically.
*/
if (!WinIsChild(vhwndHScroll, vhwndFrame)) {
WinSetParent(vhwndVScroll, vhwndFrame, FALSE);
WinSetParent(vhwndHScroll, vhwndFrame, FALSE);
}
break;
case WM_CLOSE:
WinPostMsg(hwnd, WM_QUIT, 0L, 0L);
break;
case WM_COMMAND:
/*
* processing of menu options is required
*/
MainCommand(mp1, mp2);
break;
#ifdef HELP_MANAGER_ENABLED
case HM_QUERY_KEYS_HELP:
/*
* pass the id of the Keys help panel to the system
*/
return (MRESULT)PANEL_HELPKEYS; /* id of key help panel */
break;
case HM_ERROR:
/*
* an error has occurred whilst using IPF help - report
* the error, and destroy the help instance
*/
MessageBox(vhwndFrame, IDMSG_HELPMANAGERERROR, 0,
MB_OK | MB_ERROR, TRUE);
vfHelpEnabled = FALSE;
break;
#endif
default:
/*
* default must call WinDefWindowProc()
*/
return WinDefWindowProc(hwnd, msg, mp1, mp2);
break;
}
return 0L; /* all window procedures should return 0 as a default */
} /* MainWndProc() */
/****************************************************************\
* Frame subclassed window procedure *
*--------------------------------------------------------------*
* *
* Name: FrameWndProc(hwnd, msg, mp1, mp2) *
* *
* Purpose: The purpose of the frame-window subclass procedure *
* is to restrict frame-window sizing so that it is *
* in step with the size of the client-window *
* presentation space. That is, the size of the image *
* dictates the size of the maximized window. *
* Messages intended for the frame-window procedure *
* are sent here first. *
* *
* Usage: Called for each message placed in the main *
* window's message queue *
* *
* Method: a switch statement branches to the routines to be *
* performed for each message processed. Any messages *
* not specifically process are passed to the user's *
* message processing procedure MainWndProc(). The *
* message trapped by this wndproc() are *
* WM_QUERYTRACKINFO & WM_ADJUSTWINDOWPOS which are *
* both posted to the frame procedure initially to *
* setup the default values. *
* *
* Returns: Return values are determined by each message *
* *
\****************************************************************/
MRESULT EXPENTRY FrameWndProc(hwnd, msg, mp1, mp2)
HWND hwnd; /* handle of window */
USHORT msg; /* id of message */
MPARAM mp1; /* first message parameter */
MPARAM mp2; /* second message parameter */
{
SWP swp;
PSWP pswp;
RECTL rcl;
ULONG rc;
POINTL ptl;
PTRACKINFO ptrack;
switch(msg) {
case WM_ADJUSTWINDOWPOS:
/*
* restrict the size of the window so that it never exceeds
* the maximum size of the image - only handle explicitly
* for the 'Detail' mode
*/
if (vfImgLoaded && vfDetail) {
rc = (ULONG)(*vpfnwpFrame)(hwnd, msg, mp1, mp2);
pswp = (PSWP)mp1;
swp = *pswp;
/*
* find the maximum allowed size, and ensure that
* the window size never exceeds this
*/
SizeCalculateMaxWindow(&rcl);
if (swp.cx > (SHORT)rcl.xRight)
swp.cx = (SHORT)rcl.xRight;
if (swp.cy > (SHORT)rcl.yTop)
swp.cy = (SHORT)rcl.yTop;
*pswp = swp;
return (MRESULT)rc;
} else
/* let the system handle the message */
return (*vpfnwpFrame)(hwnd, msg, mp1, mp2);
break;
case WM_QUERYTRACKINFO:
/*
* Invoke the normal frame-window procedure first in order
* to update the tracking rectangle to the new position.
*/
(*vpfnwpFrame)(hwnd, msg, mp1, mp2);
ptrack = (PTRACKINFO)mp2;
if (vfImgLoaded && vfDetail) {
/*
* Limit the size of the bounding rectangle only if the
* window is being sized.
* fs and rclBoundary are tracking information structure
* elements.
*/
if (((ptrack->fs & TF_MOVE) != TF_MOVE) &&
((ptrack->fs & TF_MOVE) ||
(ptrack->fs & TF_SETPOINTERPOS)
)) {
WinQueryWindowRect(vhwndClient, &rcl);
GpiQueryCurrentPosition(vhps, &ptl);
ptrack->rclBoundary.yTop = rcl.yBottom + ptl.y;
ptrack->rclBoundary.yBottom = rcl.yBottom + ptl.y -
vsizlImg.cy;
ptrack->rclBoundary.xLeft = rcl.xLeft + ptl.x;
ptrack->rclBoundary.xRight = rcl.xLeft + ptl.x +
vsizlImg.cx;
/*
* convert client boundary coordinates to screen
* coordinates
*/
WinMapWindowPoints(vhwndClient,
HWND_DESKTOP,
(PPOINTL)&ptrack->rclBoundary,
sizeof(RECTL)/sizeof(POINTL));
/*
* calculate equivalent frame boundary from client
* boundary data
*/
WinCalcFrameRect(vhwndFrame,
(PRECTL)&ptrack->rclBoundary,
FALSE);
ptrack->fs |= TF_ALLINBOUNDARY;
}
}
return (MRESULT)TRUE;
break;
default:
/*
* return using the normal frame window procedure
*/
return (*vpfnwpFrame)(hwnd, msg, mp1, mp2);
break;
}
return 0L; /* all window procedures should return 0 as a default */
} /* FrameWndProc() */
/****************************************************************\
* Message Box procedure
*--------------------------------------------------------------
*
* Name: MessageBox(hwndOwner, idMsg, idCaption, fsStyle, fBeep)
*
* Purpose: Displays the message box with the message
* given in idMsg retrived from the message table
* and using the style flags in fsStyle
*
* Usage: Called whenever a MessageBox is to be displayed
*
* Method: - Message string is loaded from the process'
* message table
* - Alarm beep is sounded if desired
* - Message box with the message is displayed
* - WinMessageBox return value is returned
*
* Returns: return value from WinMessageBox()
*
\****************************************************************/
SHORT MessageBox(hwndOwner, idMsg, idCaption, fsStyle, fBeep)
HWND hwndOwner; /* handle of the message box's owner */
SHORT idMsg; /* id if the message in the message table */
SHORT idCaption; /* id if the caption in the message table */
SHORT fsStyle; /* style of the message box */
BOOL fBeep; /* if TRUE, beep before message box is displayed */
{
CHAR szText[MESSAGELEN];
CHAR szCaption[MESSAGELEN];
if (!WinLoadMessage(vhab,
(HMODULE)NULL,
idMsg,
MESSAGELEN,
(PSZ)szText)) {
WinAlarm(HWND_DESKTOP, WA_ERROR);
return MBID_ERROR;
}
/*
* if idCaption specified load string else use default
* caption 'Error!'
*/
if (idCaption) {
if (!WinLoadMessage(vhab,
(HMODULE)NULL,
idCaption,
MESSAGELEN,
(PSZ)szCaption)) {
WinAlarm(HWND_DESKTOP, WA_ERROR);
return MBID_ERROR;
}
}
if (fBeep)
WinAlarm(HWND_DESKTOP, WA_ERROR);
return WinMessageBox(HWND_DESKTOP,
hwndOwner,
szText,
(idCaption ? szCaption : (PSZ)NULL),
MSGBOXID,
fsStyle);
} /* MessageBox() */
/****************************************************************\
* Main window WM_COMMAND processing procedure
*--------------------------------------------------------------
*
* Name: MainCommand(mp1, mp2)
*
* Purpose: Calls the appropriate procedures that deal with
* the selected menu item.
*
* Usage: Routine is called whenever a WM_COMMAND message
* is posted to the main window.
*
* Method: a switch statement branches on the id of the
* menu item that posted the message and the
* appropriate action for that item is taken. Any
* menu ids that are not part of the standard menu
* set are passed onto the user defined WM_COMMAND
* processing procedure.
*
* Returns:
*
\****************************************************************/
VOID MainCommand(mp1, mp2)
MPARAM mp1; /* first parameter of WM_COMMAND message */
MPARAM mp2; /* second parameter of WM_COMMAND message */
{
switch (SHORT1FROMMP(mp1)) {
case IDM_FILEOPEN:
/*
* Open file and load/draw the selected image
*/
FileOpen(mp2);
break;
case IDM_FILEEXIT:
/*
* time to leave
*/
FileExit(mp2);
break;
case IDM_VIEWDETAIL:
/*
* toggle between Detail and Non-Detail mode
*/
ViewSwitchMode();
break;
case IDM_VIEWSAVEPOSITION:
/*
* save the current image position
*/
ViewSavePosition();
break;
case IDM_VIEWRESTOREPOSITION:
/*
* save the current image position
*/
ViewRestorePosition();
break;
case IDM_VIEWFORECOLORBLACK:
case IDM_VIEWFORECOLORWHITE:
case IDM_VIEWFORECOLORBLUE:
case IDM_VIEWFORECOLORGREEN:
case IDM_VIEWFORECOLORYELLOW:
case IDM_VIEWFORECOLORRED:
case IDM_VIEWBACKCOLORBLACK:
case IDM_VIEWBACKCOLORWHITE:
case IDM_VIEWBACKCOLORBLUE:
case IDM_VIEWBACKCOLORGREEN:
case IDM_VIEWBACKCOLORYELLOW:
case IDM_VIEWBACKCOLORRED:
ViewChangeColor(SHORT1FROMMP(mp1));
break;
#ifdef HELP_MANAGER_ENABLED
case IDM_HELPHELPFORHELP:
HelpHelpForHelp(mp2);
break;
case IDM_HELPEXTENDED:
HelpExtended(mp2);
break;
case IDM_HELPINDEX:
HelpIndex(mp2);
break;
#endif
case IDM_HELPABOUT:
HelpAbout();
break;
}
} /* MainCommand() */
/****************************************************************\
* Exit list processing procedure
*--------------------------------------------------------------
*
* Name: ExitProc(usTermCode)
*
* Purpose: Cleans up certain resources when the application
* terminates
*
* Usage: Routine is called by DosExitList when the
* application exits
*
* Method: global resources, such as the main window and
* message queue, are destroyed and any system
* resources used are freed
*
* Returns: Returns EXLST_EXIT to the DosExitList handler
*
\****************************************************************/
VOID PASCAL ExitProc(usTermCode)
USHORT usTermCode; /* code for the reason for termination */
{
/* destroy the main window if it exists */
if (WinIsWindow(vhab, vhwndFrame))
WinDestroyWindow(vhwndFrame);
WinDestroyMsgQueue(hmq);
WinTerminate(vhab);
DosExitList(EXLST_EXIT, 0L); /* termination complete */
/* This routine currently doesn't use the usTermCode parameter so *\
* it is referenced here to prevent an 'Unreferenced Parameter'
\* warning at compile time */
usTermCode;
} /* ExitProc() */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.