home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 10 Tools
/
10-Tools.zip
/
focus.zip
/
FOCUS.C
< prev
next >
Wrap
Text File
|
1994-05-21
|
15KB
|
402 lines
/*----------------------------------------------------------------------------*/
/* Superclass and Focus control example */
/* */
/* Program brings up a dialog when "Run" is selected from the "File" menu. */
/* The dialog contains two entryfields and a pushbutton, along with some */
/* static text. The entryfields will not allow a focus shift from one to */
/* the other unless the entryfield contains the text "OK". Focus change */
/* IS always allowed to the pushbutton via the mouse. */
/* */
/* THIS PROGRAM RELIES ON <ONLY> DOCUMENTED MESSAGES AND BEHAVIOR. In */
/* addition to being an example of managing focus, it shows how you can */
/* alter the behavior of a standard PM control. */
/* */
/* (c) 1994 Larry Morley */
/*----------------------------------------------------------------------------*/
#define INCL_WIN
#include <os2.h>
#include <string.h>
#include "focus.h"
/*----------------------------------------------------------------------------*/
/* Defines and prototypes */
/*----------------------------------------------------------------------------*/
#define YIELD_ATTEMPTS 100
int main(VOID);
PFNWP SuperclassWindow
(PSZ szWinClass,PSZ szNewClass,PFNWP pNewWinProc,BOOL bNewClass);
VOID YieldCPU(USHORT nAttempts,ULONG ulDesiredMsg,HWND hwnd);
MRESULT EXPENTRY NewEntryFieldProc(HWND hwnd,ULONG msg,MPARAM mp1,MPARAM mp2);
MRESULT EXPENTRY ClientWinProc(HWND hwnd,ULONG msg,MPARAM mp1,MPARAM mp2);
MRESULT EXPENTRY dlgExampleProc(HWND hwnd,ULONG msg,MPARAM mp1,MPARAM mp2);
/*----------------------------------------------------------------------------*/
/* Global Variables */
/*----------------------------------------------------------------------------*/
HWND hFocus; /* The multiplex "who gets the focus" indicator */
HWND hEntryField1; /* Control window handles */
HWND hEntryField2;
PFNWP pfnOrigEntryFieldProc; /* Pointer to the entry field control's */
/* original class window procedure. */
/*----------------------------------------------------------------------------*/
HAB hAB;
HMQ hMQ;
HWND hwndFrame;
HWND hwndClient;
ULONG ulFrameFlags = FCF_TITLEBAR | FCF_SYSMENU |
FCF_SIZEBORDER | FCF_MINMAX |
FCF_SHELLPOSITION | FCF_TASKLIST |
FCF_MENU | FCF_ICON;
/*----------------------------------------------------------------------------*/
PSZ szClientClass = "ClientWindowClass";
PSZ szEntryFieldSuperClass = "WCS_ENTRYFIELD";
/*----------------------------------------------------------------------------*/
/* PFNWP SuperclassWindow */
/* (PSZ szWinClass,PSZ szNewClass,PFNWP pNewWinProc,BOOL bNewClass) */
/* */
/* This function registers a superclass of an existing class. */
/* */
/* The szWinClass parameter can be WC_FRAME, WC_BUTTON etc. -*or*- a */
/* user-defined class like "MyWindowClass". */
/* */
/* The bNewClass variable should be TRUE if the class hasn't yet been */
/* registered; false otherwise. */
/* */
/* The function returns a pointer to the original class window procedure, */
/* or NULL ((PFNWP)0) if an error occurs. */
/*----------------------------------------------------------------------------*/
PFNWP SuperclassWindow
(PSZ szWinClass,PSZ szNewClass,PFNWP pNewWinProc,BOOL bNewClass)
{
CLASSINFO ci;
PFNWP p;
if(WinQueryClassInfo(hAB,szWinClass,&ci))
{
p = ci.pfnWindowProc;
if (!WinRegisterClass(
hAB,
szNewClass,
pNewWinProc,
ci.flClassStyle & (~CS_PUBLIC),
ci.cbWindowData))
return (PFNWP)0;
return p;
}
return (PFNWP)0;
}
/*----------------------------------------------------------------------------*/
/* VOID YieldCPU(USHORT nAttempts,ULONG ulDesiredMsg,HWND hwnd) */
/* */
/* This function essentially yields the CPU by checking for a particular */
/* messages, while checking for and dispatching other messages "n" times. */
/*----------------------------------------------------------------------------*/
VOID YieldCPU(USHORT nAttempts,ULONG ulDesiredMsg,HWND hwnd)
{
QMSG qmsg;
while (nAttempts--)
if (WinPeekMsg(hAB,&qmsg,(HWND)0,(USHORT)0,(USHORT)0,PM_REMOVE))
{
if ((qmsg.msg == ulDesiredMsg) && (qmsg.hwnd == hwnd))
nAttempts = 0;
WinDispatchMsg(hAB,&qmsg);
}
return;
}
/*----------------------------------------------------------------------------*/
/* New entryfield window procedure. The entryfield will not give up the */
/* focus unless it contains the text "OK". */
/* */
/* A couple notes: */
/* */
/* WM_SETFOCUS does double duty. It normally comes from PM, but I'm using */
/* it here for three reasons: */
/* */
/* (1) With some controls, it makes the visual transition smoother. */
/* It DOES NOT change the focus. It just triggers the recapture */
/* mechanism within the other control, and (sometimes) makes it */
/* appear to have the focus before it does. */
/* */
/* (2) It allows the regain-the-focus, and the actual WM_SETFOCUS */
/* to be handled in one "case". */
/* */
/* (3) It's documented to be received when a control gains or loses */
/* the focus; so, it's expected by the controls, and has an appr- */
/* opriate priority. */
/* */
/* And, this is only the beginning. You'll probably want to, at some */
/* point, get the type of the window, and make some specific adjustments; */
/* i.e., you coud use WinQueryWindowUShort(hwnd,QWS_ID) to get the window */
/* id and go from there.. */
/* */
/*----------------------------------------------------------------------------*/
MRESULT EXPENTRY NewEntryFieldProc(HWND hwnd,ULONG msg,MPARAM mp1,MPARAM mp2)
{
static BOOL bFocus = FALSE;
switch(msg)
{
case WM_SETFOCUS:
{
if (SHORT1FROMMP(mp2)) /* Gaining focus */
{
if (hFocus)
{
/*-------------------------------*/
/* Check to see if some other */
/* window should have the focus. */
/*-------------------------------*/
if(hFocus != hwnd)
{
/*------------------------------*/
/* Use WM_SETFOCUS to trigger */
/* the focus recovery procedure */
/* in the other window and to */
/* try and make a visual change.*/
/*------------------------------*/
WinSendMsg(hFocus,msg,MPFROMHWND(hFocus),mp2);
return (*pfnOrigEntryFieldProc)(hwnd,msg,mp1,mp2);
}
}
/*------------------------------------*/
/* This handles the case of a SENT */
/* WM_FOCUS, as well as a posted one. */
/*------------------------------------*/
if (WinQueryFocus(HWND_DESKTOP) != hwnd)
{
/*---------------------------*/
/* Actually call WinSetFocus */
/*---------------------------*/
if (!bFocus)
bFocus = WinSetFocus(HWND_DESKTOP,hwnd);
/*---------------------------*/
/* Not always nescessary but */
/* won't hurt... */
/*---------------------------*/
YieldCPU(YIELD_ATTEMPTS,WM_SETFOCUS,hEntryField1);
/*---------------------------*/
/* Retry if call failed. */
/*---------------------------*/
if (!bFocus)
WinPostMsg(hwnd,msg,mp1,mp2);
}
/*--------------------------------*/
/* Housekeeping so the mechanism */
/* will work the next time around */
/*--------------------------------*/
hFocus = (HWND)0;
bFocus = FALSE;
break;
}
else
{
/*------------------------------------------------------*/
/* This window is losing the focus. Check the contents */
/* of the entryfield, and set the hFocus flag to "hwnd" */
/* if they're not correct. */
/*------------------------------------------------------*/
CHAR scrap[128];
WinQueryWindowText(hwnd,sizeof(scrap),scrap);
/*--------------------------------*/
/* Set the hFocus flag based */
/* on the text in the entryfield. */
/*--------------------------------*/
if (strcmp(scrap,"OK"))
hFocus = hwnd;
}
break;
}
}
/*-------------------------------------------*/
/* Call the original window procedure for */
/* the control; NOT WinDefWindowProc(). */
/*-------------------------------------------*/
return (*pfnOrigEntryFieldProc)(hwnd,msg,mp1,mp2);
}
/*----------------------------------------------------------------------------*/
/* A pretty standard main()... */
/*----------------------------------------------------------------------------*/
int main(VOID)
{
QMSG qmsg;
int rc;
hAB = WinInitialize((USHORT)0);
hMQ = WinCreateMsgQueue(hAB,(SHORT)0);
if (!(WinRegisterClass(
hAB,
szClientClass,
ClientWinProc,
CS_SIZEREDRAW,
(USHORT)0)))
{
rc = 1;
goto _pm_abterm;
}
if (!(hwndFrame = WinCreateStdWindow(
HWND_DESKTOP,
0L,
&ulFrameFlags,
szClientClass,
(PSZ)0,
(ULONG)0L,
(HMODULE)0,
(USHORT)ID_MAINWINDOW,
&hwndClient)))
{
rc = 2;
goto _pm_abterm;
}
WinSetWindowText(hwndFrame,"Superclass Sample");
WinShowWindow(hwndFrame,TRUE);
while (WinGetMsg(hAB,&qmsg,(HWND)0,(USHORT)0,(USHORT)0))
WinDispatchMsg(hAB,&qmsg);
_pm_abterm:
WinDestroyWindow(hwndFrame);
WinDestroyMsgQueue(hMQ);
WinTerminate(hAB);
return rc;
}
/*----------------------------------------------------------------------------*/
/* Client window procedure; again, pretty standard */
/*----------------------------------------------------------------------------*/
MRESULT EXPENTRY ClientWinProc(HWND hwnd,ULONG msg,MPARAM mp1,MPARAM mp2)
{
switch (msg)
{
case WM_CREATE:
{
if (!(pfnOrigEntryFieldProc =
SuperclassWindow(
WC_ENTRYFIELD,
szEntryFieldSuperClass,
NewEntryFieldProc,
TRUE)))
return (MRESULT)TRUE;
break;
}
case WM_COMMAND:
{
switch (SHORT1FROMMP(mp1))
{
case IDM_FILE_RUN:
{
WinDlgBox(
HWND_DESKTOP,
hwnd,
dlgExampleProc,
(HMODULE)0,
DLG_EXAMPLE,
(PVOID)0);
return (MRESULT) 0;
}
case IDM_FILE_EXIT:
{
WinPostMsg(hwnd,WM_CLOSE,(MPARAM)0,(MPARAM)0);
return (MRESULT) 0;
}
default:
return WinDefWindowProc(hwnd,msg,mp1,mp2);
}
}
case WM_PAINT:
{
HPS hPS;
hPS = WinBeginPaint(hwnd,(HPS)0,(PRECTL)0);
if (hPS)
{
GpiErase(hPS);
WinEndPaint(hPS);
}
break;
}
default:
return WinDefWindowProc(hwnd,msg,mp1,mp2);
}
return (MRESULT)FALSE;
}
/*----------------------------------------------------------------------------*/
/* Dialog that brings up the entryfields. Straightforward stuff. */
/*----------------------------------------------------------------------------*/
MRESULT dlgExampleProc(HWND hwnd,ULONG msg,MPARAM mp1,MPARAM mp2)
{
switch (msg)
{
case WM_COMMAND:
{
switch (SHORT1FROMMP(mp1))
{
case DID_OK:
WinDismissDlg(hwnd,TRUE);
return (MRESULT) 0;
}
}
}
return WinDefDlgProc(hwnd,msg,mp1,mp2);
}
/*----------------------------------------------------------------------------*/