home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PC World Komputer 1998 May
/
Pcwk5b98.iso
/
Borland
/
Cplus45
/
BC45
/
OWL1.PAK
/
WINDOW.CPP
< prev
next >
Wrap
Text File
|
1995-08-29
|
19KB
|
615 lines
// ObjectWindows - (C) Copyright 1992 by Borland International
/* --------------------------------------------------------
WINDOW.CPP
Defines type TWindow. This defines the basic behavior
of all windows.
-------------------------------------------------------- */
#include <string.h>
#include <alloc.h>
#include "applicat.h"
#include "window.h"
__link(RegScroller)
extern PTWindowsObject CreationWindow;
extern PTWindowsObject DlgCreationWindow;
extern PTWindowsObject GetObjectPtr(HWND);
#ifdef WIN31
extern long FAR PASCAL _export
InitWndProc(HWND, UINT, WPARAM, LPARAM);
#endif
#ifdef WIN30
extern LONG FAR PASCAL _export
InitWndProc(HWND_30, WORD, WORD, LONG);
#endif
/* Constructor for a TWindow. Initializes its data fields using passed
parameters and default values. */
TWindow::TWindow(PTWindowsObject AParent, LPSTR ATitle, PTModule AModule)
: TWindowsObject(AParent, AModule)
{
Title = _fstrdup(ATitle ? ATitle : "");
DefaultProc = (WNDPROC)DefWindowProc;
if ( !AParent )
Attr.Style = WS_OVERLAPPEDWINDOW;
else
if ( AParent->IsFlagSet(WB_MDIFRAME) )
{
/* Set WB_MDICHILD by default, change this if you want a
non-mdi child as a child of your TMDIFrame window. */
SetFlags(WB_MDICHILD, TRUE);
Attr.Style = WS_CLIPSIBLINGS;
}
else
Attr.Style = WS_VISIBLE;
Attr.ExStyle = 0;
Attr.X = CW_USEDEFAULT;
Attr.Y = 0;
Attr.W = CW_USEDEFAULT;
Attr.H = 0;
Attr.Param = NULL;
Attr.Menu = NULL;
Attr.Id = 0;
Scroller = NULL;
FocusChildHandle = 0;
}
/* Constructor for a TWindow which is being used in a DLL as an alias
for a non-OWL window */
TWindow::TWindow(HWND AnHWindow, PTModule AModule) :
TWindowsObject((PTWindowsObject)NULL, AModule)
{
HWND HParent;
RECT WndRect;
HWindow = AnHWindow;
int TitleLength = GetWindowTextLength(AnHWindow);
if (TitleLength > -1)
{
Title = (LPSTR)farmalloc((unsigned long)TitleLength + 1);
Title[0] = '\0'; Title[TitleLength] = '\0';
GetWindowText(AnHWindow, Title, TitleLength+1);
}
else
Title = _fstrdup("");
DefaultProc = (WNDPROC) SetWindowLong(AnHWindow, GWL_WNDPROC,
(DWORD)GetInstance());
// Note that the following two lines are not guaranteed to exactly
// reconstruct the original Style and ExStyle values passed to
// CreateWindow or CreateWindowEx. This is because some controls
// (e.g. EDIT) modify their style bits (e.g. WS_BORDER) when they
// are being created.
Attr.Style = GetWindowLong(AnHWindow, GWL_STYLE);
Attr.ExStyle = GetWindowLong(AnHWindow, GWL_EXSTYLE);
HParent = GetParent(AnHWindow);
GetWindowRect(AnHWindow, &WndRect);
Attr.H = WndRect.bottom - WndRect.top;
Attr.W = WndRect.right - WndRect.left;
if ( HParent && ((Attr.Style & WS_CHILD) == WS_CHILD) )
ScreenToClient(HParent, (LPPOINT)&WndRect);
Attr.X = WndRect.left;
Attr.Y = WndRect.top;
Attr.Param = NULL;
Attr.Menu = NULL;
Attr.Id = GetWindowWord(AnHWindow, GWW_ID);
Scroller = NULL;
FocusChildHandle = 0;
SetFlags(WB_ALIAS, TRUE);
}
/* Destructor for a TWindow. Disposes of its Scroller if the TScroller
object was constructed. */
TWindow::~TWindow()
{
if ( Scroller )
{
delete Scroller;
Scroller = NULL;
}
if ( HIWORD(Attr.Menu) )
farfree(Attr.Menu);
}
/* If Attr.Menu currently points to a string then free it. Set Attr.Menu to
the passed parameter. If the window has been created then load and
set the new menu and destroy the old one. The return value is FALSE
if SetMenu is called and fails, TRUE otherwise. Note that this function
is declared virtual, but may be called from constructors of classes
derived from TWindow. In C++, virtual functions called from constructors
are called as though they were non-virtual. Care must be taken when
redefining AssignMenu in derived classes. */
BOOL TWindow::AssignMenu(LPSTR MenuName)
{
BOOL ReturnVal = TRUE;
HMENU NewHMenu;
HMENU OldHMenu;
LPSTR TempMenuName = NULL; // handle case where MenuName==Attr.Menu
if ( HIWORD(Attr.Menu) )
TempMenuName = Attr.Menu;
if ( HIWORD(MenuName) ) // Not NULL and not an int in disguise
Attr.Menu = _fstrdup(MenuName);
else
Attr.Menu = MenuName;
if (TempMenuName)
farfree(TempMenuName);
if ( HWindow )
{
OldHMenu = GetMenu(HWindow);
NewHMenu = LoadMenu(GetModule()->hInstance, Attr.Menu);
ReturnVal = SetMenu(HWindow, NewHMenu);
if ( OldHMenu )
DestroyMenu(OldHMenu);
}
return ReturnVal;
}
BOOL TWindow::AssignMenu(int MenuId)
{
return AssignMenu((LPSTR)MAKEINTRESOURCE(MenuId));
}
/* Specifies registration attributes for the MS-Windows window
class of the TWindow, allowing instances of TWindow to be
registered. Sets the fields of the passed WNDCLASS parameter
to the default attributes appropriate for a TWindow. */
void TWindow::GetWindowClass(WNDCLASS& AWndClass)
{
AWndClass.cbClsExtra = 0;
AWndClass.cbWndExtra = 0;
AWndClass.hInstance = GetModule()->hInstance;
AWndClass.hIcon = LoadIcon(0, IDI_APPLICATION);
AWndClass.hCursor = LoadCursor(0, IDC_ARROW);
AWndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
AWndClass.lpszMenuName = NULL;
AWndClass.lpszClassName = GetClassName();
AWndClass.style = CS_HREDRAW | CS_VREDRAW;
AWndClass.lpfnWndProc = InitWndProc;
}
/* Associates an MS-Windows interface element with the TWindow object,
after creating the interface element if not already created. When
creating an element, uses the creation attributes previously set
in the Attr data field. (Simply associates the TWindow with an
already-created interface element if the "FromResource" flag is set.)
If the TWindow could be successfully associated, calls SetupWindow and
returns True. Association is not attempted if the TWindow's Status
data field is non-zero. */
BOOL TWindow::Create()
{
HWND HParent;
PTWindow TheMDIClient; // compiler doesn't know about TMDIClients yet
MDICREATESTRUCT CreateStruct;
WORD MenuOrId = 0;
if (Status == 0)
{
DisableAutoCreate();
if ( Parent == NULL )
HParent = 0;
else
HParent = Parent->HWindow;
if ( !IsFlagSet(WB_FROMRESOURCE) )
{
if ( Register() )
{
CreationWindow = this;
TWindowsObject *TmpDlgCreationWindow = DlgCreationWindow;
/* Set DlgCreationWindow to NULL so in InitWndProc we'll know
we're not being created from a resource */
DlgCreationWindow = NULL;
/* Create as MDI child if the WB_MDICHILD flag is set and Parent
has a Client */
if (IsFlagSet(WB_MDICHILD))
{
if ((TheMDIClient = (PTWindow)(Parent->GetClient())) != NULL)
{ // MDI child window
DefaultProc = (WNDPROC)DefMDIChildProc;
CreateStruct.szClass = GetClassName();
CreateStruct.szTitle = Title;
CreateStruct.hOwner = GetModule()->hInstance;
CreateStruct.x = Attr.X; CreateStruct.y = Attr.Y;
CreateStruct.cx = Attr.W; CreateStruct.cy = Attr.H;
CreateStruct.style = Attr.Style;
CreateStruct.lParam = (LONG)Attr.Param;
HWindow = (HWND)LOWORD(SendMessage(TheMDIClient->HWindow,
WM_MDICREATE, 0, (LPARAM)(&CreateStruct)));
}
else // Parent doesn't have a client, error
Status = EM_INVALIDWINDOW;
}
else // Not an MDI child window
{
if ( Attr.Menu)
MenuOrId = (WORD)LoadMenu(GetModule()->hInstance,
Attr.Menu);
else
MenuOrId = Attr.Id;
HWindow = CreateWindowEx(Attr.ExStyle, GetClassName(),
Title, Attr.Style, Attr.X, Attr.Y, Attr.W,
Attr.H, HParent, (HMENU)MenuOrId , GetModule()->hInstance,
Attr.Param);
}
DlgCreationWindow = TmpDlgCreationWindow;
}
}
else /* Windows already created window */
HWindow = GetDlgItem(HParent, Attr.Id);
if ( HWindow )
{
if ( !GetObjectPtr(HWindow) ) // predefined Windows class
{
// Retrieve the Title
int TitleLength = GetWindowTextLength(HWindow);
if (TitleLength > -1)
{
Title = (char far*)farmalloc((unsigned long)TitleLength + 1);
Title[0] = '\0'; Title[TitleLength] = '\0';
GetWindowText(HWindow, Title, TitleLength+1);
}
else
Title = _fstrdup("");
// Retrieve Attr.Style and Attr.ExStyle.
// NOTE: Some windows controls (e.g. EDIT) change the style bits
// (e.g. WS_BORDER) from their original values. If we reset
// Attr.Style and Attr.ExStyle by extracting their values from
// Windows, we will lose some of the style bits we supplied
// in the CreateWindowEx call. In the case of the ResourceId
// constructors, of course, we must retrieve these values.
if ( IsFlagSet(WB_FROMRESOURCE) )
{
Attr.Style = GetWindowLong(HWindow, GWL_STYLE);
Attr.ExStyle = GetWindowLong(HWindow, GWL_EXSTYLE);
}
// Retrieve Attr.X, Attr.Y, Attr.W and Attr.H
RECT WndRect;
GetWindowRect(HWindow, &WndRect);
Attr.H = WndRect.bottom - WndRect.top;
Attr.W = WndRect.right - WndRect.left;
if ( HParent && ((Attr.Style & WS_CHILD) == WS_CHILD) )
ScreenToClient(HParent, (LPPOINT)&WndRect);
Attr.X = WndRect.left;
Attr.Y = WndRect.top;
SetFlags(WB_PREDEFINEDCLASS, TRUE);
DefaultProc = (WNDPROC)SetWindowLong(HWindow, GWL_WNDPROC,
(DWORD)GetInstance());
SetupWindow();
}
}
else // HWindow == 0
{
if ( Attr.Menu )
DestroyMenu( HMENU( MenuOrId ));
Status = EM_INVALIDWINDOW;
}
}
return (Status == 0);
}
/* Response method for an incoming WM_MDIACTIVATE message. Calls
ActivationResponse to provide a keyboard interface for the controls
of a window. */
void TWindow::WMMDIActivate(TMessage& Msg)
{
DefWndProc(Msg);
if ( Parent )
((PTMDIFrame)Parent)->ActiveChild = (Msg.WParam ? this : NULL);
if ( !IsFlagSet(WB_ALIAS) )
{
ActivationResponse(Msg.WParam, IsIconic(HWindow));
}
}
/* Calls TWindowsObject::ActivationResponse to enable or disable the
"keyboard handler". If the TWindow has requested keyboard handling
for its messages, saves the child with the focus if it is being
deactivated and restores the focus to this child when the TWindow
is reactivated. */
void TWindow::ActivationResponse(WORD Activated, BOOL IsIconified)
{
HWND CurrentFocus;
TWindowsObject::ActivationResponse(Activated, IsIconified);
if ( IsFlagSet(WB_KBHANDLER) )
{
if ( Activated )
{
if ( FocusChildHandle && IsWindow(FocusChildHandle) &&
!IsIconified )
{
SetFocus(FocusChildHandle);
// Set to 0 so we won't reset focus if another activate comes
FocusChildHandle = 0;
}
}
else
{
CurrentFocus = GetFocus();
if ( !FocusChildHandle && CurrentFocus &&
IsChild(HWindow, CurrentFocus) )
FocusChildHandle = CurrentFocus;
}
}
}
static BOOL HasStyle(void *P, void *Style)
{
return ((PTWindowsObject)P)->HWindow &&
(GetWindowLong(((PTWindowsObject)P)->HWindow, GWL_STYLE) &
*(long *)Style) == *(long *)Style;
}
/* Initializes ("sets up") the TWindow. Called following a
successful association between an MS-Windows interface element
and a TWindow. Calls TWindowsObject::SetupWindow to create windows
in child list. If keyboard handling has been requested and
FocusChildHandle has not been set, sets it to the first child.
Sets the focus to TWindows created as MDI children. If the
TWindow has a TScroller object, calls the TScroller's
SetSBarRange to set the range of the TWindow's window scrollbars.
Can be redefined in descendant classes to perform additional
initialization. */
void TWindow::SetupWindow()
{
TWindowsObject::SetupWindow();
if ( IsFlagSet(WB_KBHANDLER) && !FocusChildHandle )
{
long Style = WS_TABSTOP;
PTWindowsObject TmpWO;
TmpWO = FirstThat(HasStyle, &Style);
if ( !TmpWO ) // no child has WS_TABSTOP
{
Style = WS_CHILD;
TmpWO = FirstThat(HasStyle, &Style);
}
if ( TmpWO )
FocusChildHandle = TmpWO->HWindow;
}
if ( IsFlagSet(WB_MDICHILD) )
SetFocus(HWindow);
if ( Scroller )
Scroller->SetSBarRange();
}
void TWindow::WMCreate(TMessage& Msg)
{
SetupWindow();
DefWndProc(Msg);
}
/* Response method for an incoming WM_HSCROLL message. If the
message is from a scrollbar control, calls DispatchScroll directly to
avoid calling TWindowsObject::WMHScroll so that GetWindowLong is
called only once. Else passes the message to the TWindow's Scroller
if it has been constructed, and calls DefWndProc. Assumes because of
a Windows bug that if the window has the scrollbar style, it will not
have scrollbar controls. */
void TWindow::WMHScroll(TMessage& Msg)
{
if ( !(GetWindowLong(HWindow, GWL_STYLE) & WS_HSCROLL) )
DispatchScroll(Msg);
else
if ( Scroller )
Scroller->HScroll(Msg.WParam, LOWORD(Msg.LParam));
else
DefWndProc(Msg);
}
/* Response method for an incoming WM_VSCROLL message. If the
message is from a scrollbar control, calls DispatchScroll directly to
avoid calling TWindowsObject::WMVScroll so that GetWindowLong is
called only once. Else passes the message to the TWindow's Scroller
if it has been constructed, and calls DefWndProc. Assumes because of
a Windows bug that if the window has the scrollbar style, it will not
have scrollbar controls. */
void TWindow::WMVScroll(TMessage& Msg)
{
if ( !(GetWindowLong(HWindow, GWL_STYLE) & WS_VSCROLL) )
DispatchScroll(Msg);
else
if ( Scroller )
Scroller->VScroll(Msg.WParam, LOWORD(Msg.LParam));
else
DefWndProc(Msg);
}
/* Response method for an incoming WM_PAINT message. Calls Paint,
performing Windows-required paint setup and cleanup before and after.
(If the TWindow has a TScroller, also calls its BeginView and EndView
methods before and after call to Paint. */
void TWindow::WMPaint(TMessage& Msg)
{
PAINTSTRUCT PaintInfo;
if ( IsFlagSet(WB_ALIAS) ) // use application-defined wndproc
DefWndProc(Msg);
else
{
BeginPaint(HWindow, &PaintInfo);
if ( Scroller )
Scroller->BeginView(PaintInfo.hdc, PaintInfo);
Paint(PaintInfo.hdc, PaintInfo);
if ( Scroller )
Scroller->EndView();
EndPaint(HWindow, &PaintInfo);
}
}
/* Redraws the contents of the TWindow after a WMPaint message
is received. Placeholder for descendant object types to redefine. */
#ifdef WIN31
void TWindow::Paint(HDC, PAINTSTRUCT _FAR &)
{ }
#endif
#ifdef WIN30
void TWindow::Paint(HDC_30, PAINTSTRUCT _FAR &)
{ }
#endif
/* Response method for an incoming WM_SIZE message. Calls the
SetPageSize and SetSBarRange methods of the TWindow's Scroller,
if it has been constructed. Also saves the normal size of the
window in Attr. */
void TWindow::WMSize(TMessage& Msg)
{
RECT WndRect;
if ( Scroller && (Msg.WParam != SIZEICONIC) )
{
Scroller->SetPageSize();
Scroller->SetSBarRange();
}
if ( Msg.WParam == SIZENORMAL )
{
GetWindowRect(HWindow, &WndRect);
Attr.H = WndRect.bottom - WndRect.top;
Attr.W = WndRect.right - WndRect.left;
}
DefWndProc(Msg);
}
/* Save the normal position of the window. If IsIconic and IsZoomed
ignore the position since it does not reflect the normal state. */
void TWindow::WMMove(TMessage& Msg)
{
RECT WndRect;
if ( !(IsIconic(HWindow) || IsZoomed(HWindow)) )
{
GetWindowRect(HWindow, &WndRect);
if ( ((GetWindowLong(HWindow, GWL_STYLE) & WS_CHILD) == WS_CHILD)
&& Parent && Parent->HWindow )
ScreenToClient(Parent->HWindow, (LPPOINT)&WndRect);
Attr.X = WndRect.left;
Attr.Y = WndRect.top;
}
DefWndProc(Msg);
}
/* Response method for an incoming WM_LBUTTONDOWN message. If
the TWindow's Scroller has been constructed and if auto-scrolling
has been requested, captures mouse input, loops until a
WM_LBUTTONUP message comes in calling the Scroller's AutoScroll
method, and then releases capture on mouse input. */
void TWindow::WMLButtonDown(TMessage& Msg)
{
MSG LoopMsg;
LoopMsg.message = 0;
if ( Scroller && Scroller->AutoMode )
{
SetCapture(HWindow);
while ( LoopMsg.message != WM_LBUTTONUP )
{
if ( PeekMessage(&LoopMsg, 0, 0, 0, PM_REMOVE) )
{
TranslateMessage(&LoopMsg);
DispatchMessage(&LoopMsg);
}
Scroller->AutoScroll();
}
ReleaseCapture();
}
DefWndProc(Msg);
}
void *TWindow::read(ipstream& is)
{
BOOL NameIsNumeric;
TWindowsObject::read(is);
if ( IsFlagSet(WB_FROMRESOURCE) )
{
DefaultProc = (WNDPROC)DefWindowProc;
memset(&Attr, 0x0, sizeof (Attr));
}
else
{
is >> Attr.Style >> Attr.ExStyle
>> Attr.X >> Attr.Y >> Attr.W
>> Attr.H >> (long)(Attr.Param);
if ( IsFlagSet(WB_MDICHILD) )
DefaultProc = (WNDPROC)DefMDIChildProc;
else
DefaultProc = (WNDPROC)DefWindowProc;
}
is >> Attr.Id;
is >> NameIsNumeric;
if ( NameIsNumeric )
is >> (long)(Attr.Menu);
else
Attr.Menu= is.freadString();
is >> Scroller;
if ( Scroller )
Scroller->Window = this;
FocusChildHandle = 0;
return this;
}
/* Writes data of the TWindow to the passed opstream. Writes its
Scroller if constructed. */
void TWindow::write(Ropstream os)
{
long SaveStyle;
BOOL NameIsNumeric;
TWindowsObject::write(os);
if ( !IsFlagSet(WB_FROMRESOURCE) )
{
SaveStyle = Attr.Style & ~(WS_MINIMIZE | WS_MAXIMIZE);
if ( HWindow )
if ( IsIconic(HWindow) )
SaveStyle |= WS_MINIMIZE;
else
if ( IsZoomed(HWindow) )
SaveStyle |= WS_MAXIMIZE;
os << SaveStyle << Attr.ExStyle << Attr.X
<< Attr.Y << Attr.W << Attr.H
<< (long)(Attr.Param);
}
os << Attr.Id;
NameIsNumeric = HIWORD(Attr.Menu) == NULL;
os << NameIsNumeric;
if ( NameIsNumeric )
os << (long)(Attr.Menu);
else
os.fwriteString(Attr.Menu);
os << Scroller;
}
PTStreamable TWindow::build()
{
return new TWindow(streamableInit);
}
TStreamableClass RegWindow("TWindow", TWindow::build, __DELTA(TWindow));