📄 interact.cxx
字号:
/*
* interact.cxx
*
* Interactor classes implementation.
*
* Portable Windows Library
*
* Copyright (c) 1993-1998 Equivalence Pty. Ltd.
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.0 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
* the License for the specific language governing rights and limitations
* under the License.
*
* The Original Code is Portable Windows Library.
*
* The Initial Developer of the Original Code is Equivalence Pty. Ltd.
*
* Portions are Copyright (C) 1993 Free Software Foundation, Inc.
* All Rights Reserved.
*
* Contributor(s): ______________________________________.
*
* $Log: interact.cxx,v $
* Revision 1.76 2001/01/29 03:00:58 robertj
* Added function to determine if window is iconic, zoomed or normal.
*
* Revision 1.75 2000/04/13 23:18:43 robertj
* Fixed problems with sizing controls with scroll bars.
*
* Revision 1.74 2000/03/17 20:32:22 robertj
* Fixed race conditions in mult-threaded windows (dialogs in particular)
*
* Revision 1.73 1999/11/16 06:51:42 robertj
* Created PCustomListBox to allow motif native code PStringListBox implementation
*
* Revision 1.72 1999/10/24 11:41:34 robertj
* Fixed bug in SetDimensions() to allow for a window with a menu.
*
* Revision 1.71 1999/08/25 02:42:13 robertj
* Fixed problem with creating windows in background threads, not happening until have a message sent.
*
* Revision 1.70 1999/08/17 03:46:42 robertj
* Fixed usage of inlines in optimised version.
*
* Revision 1.69 1999/08/07 07:13:23 robertj
* Fixed problems with "balloon help" text popup.
*
* Revision 1.68 1999/03/29 03:39:55 robertj
* Changed semantics of PTitledWindow::OnClose() function.
*
* Revision 1.67 1999/02/16 08:08:07 robertj
* MSVC 6.0 compatibility changes.
*
* Revision 1.66 1998/09/24 03:42:44 robertj
* Added open software license.
*
* Revision 1.65 1998/09/24 01:55:53 robertj
* Fixed problems with resizing windows with built in scroll bars.
*
* Revision 1.64 1998/09/22 15:15:29 robertj
* Added more support for common control callbacks, can now set message result.
* Added correction for invisible scroll bars in resizing windows.
*
* Revision 1.63 1998/09/21 13:31:03 robertj
* Changes to support new PListView class. Different call back method.
*
* Revision 1.62 1998/09/14 13:17:22 robertj
* Fixed memory leak on delete of PStringList, not deleting all its contents.
* Fixed major memory (resource) leak in control painting.
*
* Revision 1.61 1998/09/04 07:03:22 robertj
* Fixed possible crash on focus change. Depends on timeing of messages.
* Fixed SetFont() really setting font. If target is not control font may not be set in this way.
*
* Revision 1.60 1998/01/26 00:19:53 robertj
* Fixed colour of static controls in windows and dialogs.
*
* Revision 1.59 1997/04/27 05:50:31 robertj
* DLL support.
*
* Revision 1.58 1996/10/31 12:39:57 robertj
* Added RCS keywords.
*
*/
#include <pwlib.h>
#if !P_USE_INLINES
#include <pwlib/pwmisc.inl>
#endif
void PInteractor::Construct(PInteractor * par, HWND hWnd, BOOL hiddenChild)
{
parent = par;
if (parent != NULL) {
if (!hiddenChild)
parent->children.Append(this);
owner = parent->owner;
cursorMode = UseParentCursor;
}
else {
owner = &PApplication::Current();
cursorMode = UseCurrentCursor;
}
_hWnd = hWnd;
if (_hWnd != NULL) {
owner->AddWindowHandle(_hWnd, this);
HFONT hFont = (HFONT)(UINT)SendMessage(_hWnd, WM_GETFONT, 0, 0L);
if (hFont != NULL)
font = PRealFont(hFont);
else
SetFont(parent->GetFont(), TRUE);
}
else {
if (parent != NULL)
SetFont(parent->GetFont(), TRUE);
}
foregroundColour = owner->GetWindowFgColour();
backgroundColour = owner->GetWindowBkColour();
caretVisible = 1;
_in_WM_PAINT = FALSE;
mouseTrackInteractor = NULL;
mouseTrackCanvas = NULL;
hBackgroundBrush = NULL;
}
PInteractor::~PInteractor()
{
if (hBackgroundBrush != NULL)
DeleteObject(hBackgroundBrush);
if (GetFocusInteractor() == this)
SetFocusInteractor(parent);
if (parent!=NULL && parent->children.GetObjectsIndex(this) != P_MAX_INDEX) {
parent->children.DisallowDeleteObjects();
parent->children.Remove(this);
parent->children.AllowDeleteObjects();
}
if (_hWnd != NULL && _hWnd != P_DEAD_WINDOW)
DestroyWindow(_hWnd);
}
PObject::Comparison PInteractor::Compare(const PObject & obj) const
{
PAssert(obj.IsDescendant(PInteractor::Class()), PInvalidParameter);
return GetHWND() ==
((const PInteractor &)obj).GetHWND() ? EqualTo : GreaterThan;
}
void PInteractor::SetFont(const PFont & newFont, BOOL toChildren)
{
font = PRealFont(newFont);
if (_hWnd != NULL)
SetWndFont();
if (toChildren) {
for (PINDEX i = 0; i < children.GetSize(); i++)
children[i].SetFont(font, TRUE);
}
}
void PInteractor::_SetPosition(PORDINATE x, PORDINATE y,
PositionOrigin xOrigin, PositionOrigin yOrigin)
{
PDim myDim = GetStructureBounds(ScreenCoords).Dimensions();
PDim scrDim = owner->GetPrimaryScreenSize();
PDim parDim = scrDim;
PPoint org;
PInteractor * p = this;
if (parent != NULL) {
p = parent;
parDim = p->GetStructureBounds(ScreenCoords).Dimensions();
ClientToScreen(p->GetHWND(), org);
}
switch (xOrigin) {
case TopLeftParent:
case CentreParent :
case BottomRightParent :
x = p->ToPixelsX(x) + org.X();
break;
case TopLeftPixels:
case CentrePixels :
case BottomRightPixels :
x = x + org.X();
}
switch (xOrigin) {
case CentreParent :
case CentrePixels :
x += ((PORDINATE)parDim.Width() - (PORDINATE)myDim.Width())/2;
break;
case BottomRightParent :
case BottomRightPixels :
x += (PORDINATE)parDim.Width() - (PORDINATE)myDim.Width();
break;
case CentreScreen :
x += ((PORDINATE)scrDim.Width() - (PORDINATE)myDim.Width())/2;
break;
case BottomRightScreen :
x = owner->GetScreenRect().Right() - (PORDINATE)myDim.Width();
}
switch (yOrigin) {
case TopLeftParent:
case CentreParent :
case BottomRightParent :
y = p->ToPixelsY(y) + org.Y();
break;
case TopLeftPixels:
case CentrePixels :
case BottomRightPixels :
y = y + org.Y();
}
switch (yOrigin) {
case CentreParent :
case CentrePixels :
y += ((PORDINATE)parDim.Height() - (PORDINATE)myDim.Height())/2;
break;
case BottomRightParent :
case BottomRightPixels :
y += (PORDINATE)parDim.Height() - (PORDINATE)myDim.Height();
break;
case CentreScreen :
y += ((PORDINATE)scrDim.Height() - (PORDINATE)myDim.Height())/2;
break;
case BottomRightScreen :
y = owner->GetScreenRect().Height() - (PORDINATE)myDim.Height();
}
if ((_styleBits&0xc0000000) == WS_CHILD) {
POINT pt;
pt.x = x;
pt.y = y;
ScreenToClient(p->GetHWND(), &pt);
x = (PORDINATE)pt.x;
y = (PORDINATE)pt.y;
}
SetWindowPos(GetHWND(), NULL, x, y, 0, 0, SWP_NOSIZE|SWP_NOZORDER);
}
PPoint PInteractor::GetPosition(CoordinateSystem coords) const
{
RECT r;
GetWindowRect(GetHWND(), &r);
PPoint p((PORDINATE)r.left, (PORDINATE)r.top);
if (coords == ScreenCoords)
return p;
if (GetParent() != NULL)
ScreenToClient(GetParent()->GetHWND(), p);
if (coords == PixelCoords)
return p;
const PInteractor * par = parent != NULL ? parent : this;
return par->FromPixels(p);
}
PPoint PInteractor::ToScreen(const PPoint & pt, CoordinateSystem coords) const
{
PPoint p;
switch (coords) {
case LocalCoords :
p = ToPixels(pt);
break;
case PixelCoords :
p = pt;
break;
case ScreenCoords :
return pt;
}
ClientToScreen(GetHWND(), p);
return p;
}
PPoint PInteractor::FromScreen(const PPoint & pt, CoordinateSystem coords) const
{
if (coords == ScreenCoords)
return pt;
PPoint p = pt;
ScreenToClient(GetHWND(), p);
return coords == PixelCoords ? p : ToPixels(p);
}
void PInteractor::_SetDimensions(PDIMENSION width, PDIMENSION height,
CoordinateSystem coords)
{
GetHWND();
if (coords == LocalCoords) {
width = ToPixelsDX(width);
height = ToPixelsDY(height);
}
switch (_styleBits&WS_CAPTION) {
case WS_CAPTION :
height += (PDIMENSION)GetSystemMetrics(SM_CYCAPTION);
break;
case WS_BORDER :
width += (PDIMENSION)GetSystemMetrics(SM_CXBORDER)*2;
height += (PDIMENSION)GetSystemMetrics(SM_CYBORDER)*2;
break;
case WS_DLGFRAME :
width += (PDIMENSION)GetSystemMetrics(SM_CXDLGFRAME)*2;
height += (PDIMENSION)GetSystemMetrics(SM_CYDLGFRAME)*2;
break;
}
if ((_styleBits&WS_VSCROLL) != 0 && AdjustDimensionForScrollBar(SB_VERT))
width += (PDIMENSION)GetSystemMetrics(SM_CXVSCROLL);
if ((_styleBits&WS_HSCROLL) != 0 && AdjustDimensionForScrollBar(SB_HORZ))
height += (PDIMENSION)GetSystemMetrics(SM_CYHSCROLL);
if ((_exStyleBits&WS_EX_DLGMODALFRAME) != 0) {
width += (PDIMENSION)GetSystemMetrics(SM_CXDLGFRAME)*2;
height += (PDIMENSION)GetSystemMetrics(SM_CYDLGFRAME)*2;
}
else if ((_styleBits&WS_THICKFRAME) != 0) {
width += (PDIMENSION)GetSystemMetrics(SM_CXFRAME)*2;
height += (PDIMENSION)GetSystemMetrics(SM_CYFRAME)*2;
}
if ((_styleBits&(WS_CHILD|WS_POPUP|WS_OVERLAPPED)) != WS_CHILD && GetMenu(_hWnd) != NULL)
height += (PDIMENSION)GetSystemMetrics(SM_CYMENU);
SetWindowPos(_hWnd, NULL, 0, 0, width, height, SWP_NOMOVE|SWP_NOZORDER);
}
BOOL PInteractor::AdjustDimensionForScrollBar(UINT bar) const
{
SCROLLINFO inf;
inf.cbSize = sizeof(inf);
inf.fMask = SIF_RANGE|SIF_PAGE;
GetScrollInfo(_hWnd, bar, &inf);
return inf.nMin != inf.nMax && inf.nPage < (UINT)(inf.nMax - inf.nMin);
}
PDim PInteractor::GetDimensions(CoordinateSystem coords) const
{
PRect r;
GetClientRect(GetHWND(), r);
if (coords != LocalCoords)
return r.Dimensions();
return FromPixels(r.Dimensions());
}
PRect PInteractor::GetStructureBounds(CoordinateSystem coords) const
{
PRect r;
GetWindowRect(GetHWND(), r);
if (coords == ScreenCoords)
return r;
PPoint p1(r.Origin());
ScreenToClient(GetHWND(), p1);
PPoint p2(r.Corner());
ScreenToClient(GetHWND(), p2);
if (coords == PixelCoords)
return PRect(p1, p2);
return PRect(FromPixels(p1), FromPixels(p2));
}
void PInteractor::_Invalidate(PORDINATE x, PORDINATE y,
PDIMENSION dx, PDIMENSION dy,
CoordinateSystem coords)
{
RECT cr;
GetClientRect(GetHWND(), &cr);
RECT r;
switch (coords) {
case LocalCoords :
r.left = ToPixelsX(x);
r.top = ToPixelsY(y);
r.right = ToPixelsX(x+dx);
r.bottom = ToPixelsY(y+dy);
break;
case PixelCoords :
r.left = x;
r.top = y;
r.right = x+dx;
r.bottom = y+dy;
break;
default : // ScreenCoords
RECT wr;
GetWindowRect(GetHWND(), &wr);
r.left = wr.left+x;
r.top = wr.top+y;
r.right = x+dx;
r.bottom = y+dy;
}
if (r.left < cr.left)
r.left = cr.left;
if (r.right > cr.right)
r.right = cr.right;
if (r.top < cr.top)
r.top = cr.top;
if (r.bottom > cr.bottom)
r.bottom = cr.bottom;
InvalidateRect(_hWnd, &r, FALSE);
}
void PInteractor::_Validate(PORDINATE x, PORDINATE y,
PDIMENSION dx, PDIMENSION dy,
CoordinateSystem coords)
{
RECT cr;
GetClientRect(GetHWND(), &cr);
RECT r;
switch (coords) {
case LocalCoords :
r.left = ToPixelsX(x);
r.top = ToPixelsY(y);
r.right = ToPixelsX(x+dx);
r.bottom = ToPixelsY(y+dy);
break;
case PixelCoords :
r.left = x;
r.top = y;
r.right = x+dx;
r.bottom = y+dy;
break;
default : // ScreenCoords
RECT wr;
GetWindowRect(GetHWND(), &wr);
r.left = wr.left+x;
r.top = wr.top+y;
r.right = x+dx;
r.bottom = y+dy;
}
if (r.left < cr.left)
r.left = cr.left;
if (r.right > cr.right)
r.right = cr.right;
if (r.top < cr.top)
r.top = cr.top;
if (r.bottom > cr.bottom)
r.bottom = cr.bottom;
ValidateRect(GetHWND(), &r);
}
void PInteractor::ReleaseMouse()
{
if (HasMouse())
ReleaseCapture();
}
void PInteractor::SetCursorToParent(BOOL useParent)
{
if (cursorMode == UseParentCursor || cursorMode == UseCurrentCursor) {
cursorMode = useParent ? UseParentCursor : UseCurrentCursor;
parent->SetWndCursor();
}
}
void PInteractor::SetCursor(const PCursor & newCursor)
{
if (cursorMode == UseParentCursor || cursorMode == UseCurrentCursor) {
cursorMode = UseCurrentCursor;
cursor = newCursor;
if (_hWnd != P_DEAD_WINDOW &&
ContainsPoint(GetCursorPos(ScreenCoords), ScreenCoords))
SetWndCursor();
}
}
void PInteractor::SetWndCursor() const
{
if (cursorMode == UseParentCursor && parent != NULL)
parent->SetWndCursor();
else
::SetCursor(cursor.GetHCURSOR());
}
void PInteractor::_SetCursorPos(PORDINATE x, PORDINATE y,
CoordinateSystem coords)
{
PPoint p(x, y);
switch (coords) {
case LocalCoords :
p = ToPixels(p);
case PixelCoords :
ClientToScreen(GetHWND(), p);
break;
case ScreenCoords :
break;
}
::SetCursorPos(p.X(), p.Y());
}
PPoint PInteractor::GetCursorPos(CoordinateSystem coords) const
{
PPoint p;
::GetCursorPos(p);
if (coords == ScreenCoords)
return p;
::ScreenToClient(GetHWND(), p);
if (coords == PixelCoords)
return p;
return FromPixels(p);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -