interact.cxx
上传用户:hzhsqp
上传日期:2007-01-06
资源大小:1600k
文件大小:43k
源码类别:

IP电话/视频会议

开发平台:

Visual C++

  1. /*
  2.  * interact.cxx
  3.  *
  4.  * Interactor classes implementation.
  5.  *
  6.  * Portable Windows Library
  7.  *
  8.  * Copyright (c) 1993-1998 Equivalence Pty. Ltd.
  9.  *
  10.  * The contents of this file are subject to the Mozilla Public License
  11.  * Version 1.0 (the "License"); you may not use this file except in
  12.  * compliance with the License. You may obtain a copy of the License at
  13.  * http://www.mozilla.org/MPL/
  14.  *
  15.  * Software distributed under the License is distributed on an "AS IS"
  16.  * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
  17.  * the License for the specific language governing rights and limitations
  18.  * under the License.
  19.  *
  20.  * The Original Code is Portable Windows Library.
  21.  *
  22.  * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
  23.  *
  24.  * Portions are Copyright (C) 1993 Free Software Foundation, Inc.
  25.  * All Rights Reserved.
  26.  *
  27.  * Contributor(s): ______________________________________.
  28.  *
  29.  * $Log: interact.cxx,v $
  30.  * Revision 1.75  2000/04/13 23:18:43  robertj
  31.  * Fixed problems with sizing controls with scroll bars.
  32.  *
  33.  * Revision 1.74  2000/03/17 20:32:22  robertj
  34.  * Fixed race conditions in mult-threaded windows (dialogs in particular)
  35.  *
  36.  * Revision 1.73  1999/11/16 06:51:42  robertj
  37.  * Created PCustomListBox to allow motif native code PStringListBox implementation
  38.  *
  39.  * Revision 1.72  1999/10/24 11:41:34  robertj
  40.  * Fixed bug in SetDimensions() to allow for a window with a menu.
  41.  *
  42.  * Revision 1.71  1999/08/25 02:42:13  robertj
  43.  * Fixed problem with creating windows in background threads, not happening until have a message sent.
  44.  *
  45.  * Revision 1.70  1999/08/17 03:46:42  robertj
  46.  * Fixed usage of inlines in optimised version.
  47.  *
  48.  * Revision 1.69  1999/08/07 07:13:23  robertj
  49.  * Fixed problems with "balloon help" text popup.
  50.  *
  51.  * Revision 1.68  1999/03/29 03:39:55  robertj
  52.  * Changed semantics of PTitledWindow::OnClose() function.
  53.  *
  54.  * Revision 1.67  1999/02/16 08:08:07  robertj
  55.  * MSVC 6.0 compatibility changes.
  56.  *
  57.  * Revision 1.66  1998/09/24 03:42:44  robertj
  58.  * Added open software license.
  59.  *
  60.  * Revision 1.65  1998/09/24 01:55:53  robertj
  61.  * Fixed problems with resizing windows with built in scroll bars.
  62.  *
  63.  * Revision 1.64  1998/09/22 15:15:29  robertj
  64.  * Added more support for common control callbacks, can now set message result.
  65.  * Added correction for invisible scroll bars in resizing windows.
  66.  *
  67.  * Revision 1.63  1998/09/21 13:31:03  robertj
  68.  * Changes to support new PListView class. Different call back method.
  69.  *
  70.  * Revision 1.62  1998/09/14 13:17:22  robertj
  71.  * Fixed memory leak on delete of PStringList, not deleting all its contents.
  72.  * Fixed major memory (resource) leak in control painting.
  73.  *
  74.  * Revision 1.61  1998/09/04 07:03:22  robertj
  75.  * Fixed possible crash on focus change. Depends on timeing of messages.
  76.  * Fixed SetFont() really setting font. If target is not control font may not be set in this way.
  77.  *
  78.  * Revision 1.60  1998/01/26 00:19:53  robertj
  79.  * Fixed colour of static controls in windows and dialogs.
  80.  *
  81.  * Revision 1.59  1997/04/27 05:50:31  robertj
  82.  * DLL support.
  83.  *
  84.  * Revision 1.58  1996/10/31 12:39:57  robertj
  85.  * Added RCS keywords.
  86.  *
  87.  */
  88. #include <pwlib.h>
  89. #if !P_USE_INLINES
  90. #include <pwlib/pwmisc.inl>
  91. #endif
  92. void PInteractor::Construct(PInteractor * par, HWND hWnd, BOOL hiddenChild)
  93. {
  94.   parent = par;
  95.   if (parent != NULL) {
  96.     if (!hiddenChild)
  97.       parent->children.Append(this);
  98.     owner = parent->owner;
  99.     cursorMode = UseParentCursor;
  100.   }
  101.   else {
  102.     owner = &PApplication::Current();
  103.     cursorMode = UseCurrentCursor;
  104.   }
  105.   _hWnd = hWnd;
  106.   if (_hWnd != NULL) {
  107.     owner->AddWindowHandle(_hWnd, this);
  108.     HFONT hFont = (HFONT)(UINT)SendMessage(_hWnd, WM_GETFONT, 0, 0L);
  109.     if (hFont != NULL)
  110.       font = PRealFont(hFont);
  111.     else
  112.       SetFont(parent->GetFont(), TRUE);
  113.   }
  114.   else {
  115.     if (parent != NULL)
  116.       SetFont(parent->GetFont(), TRUE);
  117.   }
  118.   foregroundColour = owner->GetWindowFgColour();
  119.   backgroundColour = owner->GetWindowBkColour();
  120.   caretVisible = 1;
  121.   _in_WM_PAINT = FALSE;
  122.   mouseTrackInteractor = NULL;
  123.   mouseTrackCanvas = NULL;
  124.   hBackgroundBrush = NULL;
  125. }
  126. PInteractor::~PInteractor()
  127. {
  128.   if (hBackgroundBrush != NULL)
  129.     DeleteObject(hBackgroundBrush);
  130.   if (GetFocusInteractor() == this)
  131.     SetFocusInteractor(parent);
  132.   if (parent!=NULL && parent->children.GetObjectsIndex(this) != P_MAX_INDEX) {
  133.     parent->children.DisallowDeleteObjects();
  134.     parent->children.Remove(this);
  135.     parent->children.AllowDeleteObjects();
  136.   }
  137.   if (_hWnd != NULL && _hWnd != P_DEAD_WINDOW)
  138.     DestroyWindow(_hWnd);
  139. }
  140. PObject::Comparison PInteractor::Compare(const PObject & obj) const
  141. {
  142.   PAssert(obj.IsDescendant(PInteractor::Class()), PInvalidParameter);
  143.   return GetHWND() ==
  144.                 ((const PInteractor &)obj).GetHWND() ? EqualTo : GreaterThan;
  145. }
  146. void PInteractor::SetFont(const PFont & newFont, BOOL toChildren)
  147. {
  148.   font = PRealFont(newFont);
  149.   if (_hWnd != NULL)
  150.     SetWndFont();
  151.   if (toChildren) {
  152.     for (PINDEX i = 0; i < children.GetSize(); i++)
  153.       children[i].SetFont(font, TRUE);
  154.   }
  155. }
  156. void PInteractor::_SetPosition(PORDINATE x, PORDINATE y,
  157.                                PositionOrigin xOrigin, PositionOrigin yOrigin)
  158. {
  159.   PDim myDim = GetStructureBounds(ScreenCoords).Dimensions();
  160.   PDim scrDim = owner->GetPrimaryScreenSize();
  161.   PDim parDim = scrDim;
  162.   PPoint org;
  163.   PInteractor * p = this;
  164.   if (parent != NULL) {
  165.     p = parent;
  166.     parDim = p->GetStructureBounds(ScreenCoords).Dimensions();
  167.     ClientToScreen(p->GetHWND(), org);
  168.   }
  169.   switch (xOrigin) {
  170.     case TopLeftParent:
  171.     case CentreParent :
  172.     case BottomRightParent :
  173.       x = p->ToPixelsX(x) + org.X();
  174.       break;
  175.     case TopLeftPixels:
  176.     case CentrePixels :
  177.     case BottomRightPixels :
  178.       x = x + org.X();
  179.   }
  180.   switch (xOrigin) {
  181.     case CentreParent :
  182.     case CentrePixels :
  183.       x += ((PORDINATE)parDim.Width() - (PORDINATE)myDim.Width())/2;
  184.       break;
  185.     case BottomRightParent :
  186.     case BottomRightPixels :
  187.       x += (PORDINATE)parDim.Width() - (PORDINATE)myDim.Width();
  188.       break;
  189.     case CentreScreen :
  190.       x += ((PORDINATE)scrDim.Width() - (PORDINATE)myDim.Width())/2;
  191.       break;
  192.     case BottomRightScreen :
  193.       x = owner->GetScreenRect().Right() - (PORDINATE)myDim.Width();
  194.   }
  195.   switch (yOrigin) {
  196.     case TopLeftParent:
  197.     case CentreParent :
  198.     case BottomRightParent :
  199.       y = p->ToPixelsY(y) + org.Y();
  200.       break;
  201.     case TopLeftPixels:
  202.     case CentrePixels :
  203.     case BottomRightPixels :
  204.       y = y + org.Y();
  205.   }
  206.   switch (yOrigin) {
  207.     case CentreParent :
  208.     case CentrePixels :
  209.       y += ((PORDINATE)parDim.Height() - (PORDINATE)myDim.Height())/2;
  210.       break;
  211.     case BottomRightParent :
  212.     case BottomRightPixels :
  213.       y += (PORDINATE)parDim.Height() - (PORDINATE)myDim.Height();
  214.       break;
  215.     case CentreScreen :
  216.       y += ((PORDINATE)scrDim.Height() - (PORDINATE)myDim.Height())/2;
  217.       break;
  218.     case BottomRightScreen :
  219.       y = owner->GetScreenRect().Height() - (PORDINATE)myDim.Height();
  220.   }
  221.   if ((_styleBits&0xc0000000) == WS_CHILD) {
  222.     POINT pt;
  223.     pt.x = x;
  224.     pt.y = y;
  225.     ScreenToClient(p->GetHWND(), &pt);
  226.     x = (PORDINATE)pt.x;
  227.     y = (PORDINATE)pt.y;
  228.   }
  229.   SetWindowPos(GetHWND(), NULL, x, y, 0, 0, SWP_NOSIZE|SWP_NOZORDER);
  230. }
  231. PPoint PInteractor::GetPosition(CoordinateSystem coords) const
  232. {
  233.   RECT r;
  234.   GetWindowRect(GetHWND(), &r);
  235.   PPoint p((PORDINATE)r.left, (PORDINATE)r.top);
  236.   if (coords == ScreenCoords)
  237.     return p;
  238.   if (GetParent() != NULL)
  239.     ScreenToClient(GetParent()->GetHWND(), p);
  240.   if (coords == PixelCoords)
  241.     return p;
  242.   const PInteractor * par = parent != NULL ? parent : this;
  243.   return par->FromPixels(p);
  244. }
  245. PPoint PInteractor::ToScreen(const PPoint & pt, CoordinateSystem coords) const
  246. {
  247.   PPoint p;
  248.   switch (coords) {
  249.     case LocalCoords :
  250.       p = ToPixels(pt);
  251.       break;
  252.     case PixelCoords :
  253.       p = pt;
  254.       break;
  255.     case ScreenCoords :
  256.       return pt;
  257.   }
  258.   ClientToScreen(GetHWND(), p);
  259.   return p;
  260. }
  261. PPoint PInteractor::FromScreen(const PPoint & pt, CoordinateSystem coords) const
  262. {
  263.   if (coords == ScreenCoords)
  264.     return pt;
  265.   PPoint p = pt;
  266.   ScreenToClient(GetHWND(), p);
  267.   return coords == PixelCoords ? p : ToPixels(p);
  268. }
  269. void PInteractor::_SetDimensions(PDIMENSION width, PDIMENSION height,
  270.                                  CoordinateSystem coords)
  271. {
  272.   GetHWND();
  273.   if (coords == LocalCoords) {
  274.     width = ToPixelsDX(width);
  275.     height = ToPixelsDY(height);
  276.   }
  277.   switch (_styleBits&WS_CAPTION) {
  278.     case WS_CAPTION :
  279.       height += (PDIMENSION)GetSystemMetrics(SM_CYCAPTION);
  280.       break;
  281.     case WS_BORDER :
  282.       width += (PDIMENSION)GetSystemMetrics(SM_CXBORDER)*2;
  283.       height += (PDIMENSION)GetSystemMetrics(SM_CYBORDER)*2;
  284.       break;
  285.     case WS_DLGFRAME :
  286.       width += (PDIMENSION)GetSystemMetrics(SM_CXDLGFRAME)*2;
  287.       height += (PDIMENSION)GetSystemMetrics(SM_CYDLGFRAME)*2;
  288.       break;
  289.   }
  290.   if ((_styleBits&WS_VSCROLL) != 0 && AdjustDimensionForScrollBar(SB_VERT))
  291.     width += (PDIMENSION)GetSystemMetrics(SM_CXVSCROLL);
  292.   if ((_styleBits&WS_HSCROLL) != 0 && AdjustDimensionForScrollBar(SB_HORZ))
  293.     height += (PDIMENSION)GetSystemMetrics(SM_CYHSCROLL);
  294.   if ((_exStyleBits&WS_EX_DLGMODALFRAME) != 0) {
  295.     width += (PDIMENSION)GetSystemMetrics(SM_CXDLGFRAME)*2;
  296.     height += (PDIMENSION)GetSystemMetrics(SM_CYDLGFRAME)*2;
  297.   }
  298.   else if ((_styleBits&WS_THICKFRAME) != 0) {
  299.     width += (PDIMENSION)GetSystemMetrics(SM_CXFRAME)*2;
  300.     height += (PDIMENSION)GetSystemMetrics(SM_CYFRAME)*2;
  301.   }
  302.   if ((_styleBits&(WS_CHILD|WS_POPUP|WS_OVERLAPPED)) != WS_CHILD && GetMenu(_hWnd) != NULL)
  303.     height += (PDIMENSION)GetSystemMetrics(SM_CYMENU);
  304.   SetWindowPos(_hWnd, NULL, 0, 0, width, height, SWP_NOMOVE|SWP_NOZORDER);
  305. }
  306. BOOL PInteractor::AdjustDimensionForScrollBar(UINT bar) const
  307. {
  308.   SCROLLINFO inf;
  309.   inf.cbSize = sizeof(inf);
  310.   inf.fMask = SIF_RANGE|SIF_PAGE;
  311.   GetScrollInfo(_hWnd, bar, &inf);
  312.   return inf.nMin != inf.nMax && inf.nPage < (UINT)(inf.nMax - inf.nMin);
  313. }
  314. PDim PInteractor::GetDimensions(CoordinateSystem coords) const
  315. {
  316.   PRect r;
  317.   GetClientRect(GetHWND(), r);
  318.   if (coords != LocalCoords)
  319.     return r.Dimensions();
  320.   return FromPixels(r.Dimensions());
  321. }
  322. PRect PInteractor::GetStructureBounds(CoordinateSystem coords) const
  323. {
  324.   PRect r;
  325.   GetWindowRect(GetHWND(), r);
  326.   if (coords == ScreenCoords)
  327.     return r;
  328.   PPoint p1(r.Origin());
  329.   ScreenToClient(GetHWND(), p1);
  330.   PPoint p2(r.Corner());
  331.   ScreenToClient(GetHWND(), p2);
  332.   if (coords == PixelCoords)
  333.     return PRect(p1, p2);
  334.   return PRect(FromPixels(p1), FromPixels(p2));
  335. }
  336. void PInteractor::_Invalidate(PORDINATE x, PORDINATE y,
  337.                               PDIMENSION dx, PDIMENSION dy,
  338.                               CoordinateSystem coords)
  339. {
  340.   RECT cr;
  341.   GetClientRect(GetHWND(), &cr);
  342.   RECT r;
  343.   switch (coords) {
  344.     case LocalCoords :
  345.       r.left = ToPixelsX(x);
  346.       r.top = ToPixelsY(y);
  347.       r.right = ToPixelsX(x+dx);
  348.       r.bottom = ToPixelsY(y+dy);
  349.       break;
  350.     case PixelCoords :
  351.       r.left = x;
  352.       r.top = y;
  353.       r.right = x+dx;
  354.       r.bottom = y+dy;
  355.       break;
  356.     default : // ScreenCoords
  357.       RECT wr;
  358.       GetWindowRect(GetHWND(), &wr);
  359.       r.left = wr.left+x;
  360.       r.top = wr.top+y;
  361.       r.right = x+dx;
  362.       r.bottom = y+dy;
  363.   }
  364.   if (r.left < cr.left)
  365.     r.left = cr.left;
  366.   if (r.right > cr.right)
  367.     r.right = cr.right;
  368.   if (r.top < cr.top)
  369.     r.top = cr.top;
  370.   if (r.bottom > cr.bottom)
  371.     r.bottom = cr.bottom;
  372.   InvalidateRect(_hWnd, &r, FALSE);
  373. }
  374. void PInteractor::_Validate(PORDINATE x, PORDINATE y,
  375.                             PDIMENSION dx, PDIMENSION dy,
  376.                             CoordinateSystem coords)
  377. {
  378.   RECT cr;
  379.   GetClientRect(GetHWND(), &cr);
  380.   RECT r;
  381.   switch (coords) {
  382.     case LocalCoords :
  383.       r.left = ToPixelsX(x);
  384.       r.top = ToPixelsY(y);
  385.       r.right = ToPixelsX(x+dx);
  386.       r.bottom = ToPixelsY(y+dy);
  387.       break;
  388.     case PixelCoords :
  389.       r.left = x;
  390.       r.top = y;
  391.       r.right = x+dx;
  392.       r.bottom = y+dy;
  393.       break;
  394.     default : // ScreenCoords
  395.       RECT wr;
  396.       GetWindowRect(GetHWND(), &wr);
  397.       r.left = wr.left+x;
  398.       r.top = wr.top+y;
  399.       r.right = x+dx;
  400.       r.bottom = y+dy;
  401.   }
  402.   if (r.left < cr.left)
  403.     r.left = cr.left;
  404.   if (r.right > cr.right)
  405.     r.right = cr.right;
  406.   if (r.top < cr.top)
  407.     r.top = cr.top;
  408.   if (r.bottom > cr.bottom)
  409.     r.bottom = cr.bottom;
  410.   ValidateRect(GetHWND(), &r);
  411. }
  412. void PInteractor::ReleaseMouse()
  413. {
  414.   if (HasMouse())
  415.     ReleaseCapture();
  416. }
  417. void PInteractor::SetCursorToParent(BOOL useParent)
  418. {
  419.   if (cursorMode == UseParentCursor || cursorMode == UseCurrentCursor) {
  420.     cursorMode = useParent ? UseParentCursor : UseCurrentCursor;
  421.     parent->SetWndCursor();
  422.   }
  423. }
  424. void PInteractor::SetCursor(const PCursor & newCursor)
  425. {
  426.   if (cursorMode == UseParentCursor || cursorMode == UseCurrentCursor) {
  427.     cursorMode = UseCurrentCursor;
  428.     cursor = newCursor;
  429.     if (_hWnd != P_DEAD_WINDOW &&
  430.                     ContainsPoint(GetCursorPos(ScreenCoords), ScreenCoords))
  431.       SetWndCursor();
  432.   }
  433. }
  434. void PInteractor::SetWndCursor() const
  435. {
  436.   if (cursorMode == UseParentCursor && parent != NULL)
  437.     parent->SetWndCursor();
  438.   else
  439.     ::SetCursor(cursor.GetHCURSOR());
  440. }
  441. void PInteractor::_SetCursorPos(PORDINATE x, PORDINATE y,
  442.                                 CoordinateSystem coords)
  443. {
  444.   PPoint p(x, y);
  445.   switch (coords) {
  446.     case LocalCoords :
  447.       p = ToPixels(p);
  448.     case PixelCoords :
  449.       ClientToScreen(GetHWND(), p);
  450.       break;
  451.     case ScreenCoords :
  452.       break;
  453.   }
  454.   ::SetCursorPos(p.X(), p.Y());
  455. }
  456. PPoint PInteractor::GetCursorPos(CoordinateSystem coords) const
  457. {
  458.   PPoint p;
  459.   ::GetCursorPos(p);
  460.   if (coords == ScreenCoords)
  461.     return p;
  462.   ::ScreenToClient(GetHWND(), p);
  463.   if (coords == PixelCoords)
  464.     return p;
  465.   return FromPixels(p);
  466. }
  467. PDim PInteractor::GetBorderSize() const
  468. {
  469.   return owner->GetBorderSize();
  470. }
  471. const PColour & PInteractor::GetBorderColour() const
  472. {
  473.   return owner->GetActiveBorderColour();
  474. }
  475. void PInteractor::SetBackgroundColour(const PColour & newColour)
  476. {
  477.   backgroundColour = newColour;
  478.   Invalidate();
  479. }
  480. BOOL PInteractor::HandleScrollBar(HWND scrWnd, WPARAM code, int trackVal)
  481. {
  482.   if (scrWnd == NULL)
  483.     return FALSE;
  484.   PScrollBar * bar = (PScrollBar *)owner->GetWindowObject(scrWnd);
  485.   if (bar == NULL)
  486.     return FALSE;
  487.   OnControlNotify(*bar, bar->TrackScrollBar(code, trackVal));
  488.   return TRUE;
  489. }
  490. BOOL PInteractor::HandleCommand(NMHDR & msg)
  491. {
  492.   if (msg.hwndFrom == NULL)
  493.     return FALSE;
  494.   PControl * control = (PControl*)owner->GetWindowObject(msg.hwndFrom);
  495.   if (control == NULL)
  496.     return FALSE;
  497.   _WindowsMessage * oldMessage = control->_msg;
  498.   control->_msg = _msg;
  499.   int option = control->TranslateOption(msg);
  500.   control->_msg = oldMessage;
  501.   if (option < 0)
  502.     return option < -1;
  503.   OnControlNotify(*control, option);
  504.   return !control->GetNotifier().IsNULL();
  505. }
  506. BOOL PInteractor::HandleDrawItem(const DRAWITEMSTRUCT FAR * dis)
  507. {
  508.   PControl * item = (PControl *)owner->GetWindowObject(dis->hwndItem);
  509.   if (item == NULL)
  510.     return FALSE;
  511.   switch (dis->CtlType) {
  512.     case ODT_BUTTON :
  513.       if (!((PPushButton *)item)->IsOwnerDraw())
  514.         return FALSE;
  515.       break;
  516.     case ODT_LISTBOX :
  517.       if (!item->IsDescendant(PCustomListBox::Class()))
  518.         return FALSE;
  519.       break;
  520.     default :
  521.       return FALSE;
  522.   }
  523.   PDrawCanvas canvas(item, dis->hDC, FALSE, FALSE);
  524.   BOOL focus = (dis->itemState&ODS_FOCUS) != 0;
  525.   BOOL select = (dis->itemState&ODS_SELECTED) != 0;
  526.   if (dis->CtlType == ODT_BUTTON) {
  527.     PPushButton * btn = (PPushButton *)item;
  528.     PRect bounds = btn->DrawButtonSurround(canvas, select);
  529.     btn->OnDrawFace(canvas, bounds, focus, select);
  530.   }
  531.   else {
  532.     PRect bounds = canvas.FromPixels(PRect(dis->rcItem));
  533.     if ((int)dis->itemID < 0)
  534.       canvas.DrawFocusRect(bounds);
  535.     else {
  536.       if (!item->IsEnabled()) {
  537.         canvas.SetTextFgColour(owner->GetGrayTextColour());
  538.         canvas.SetTextBkColour(owner->GetWindowBkColour());
  539.       }
  540.       else if (select) {
  541.         canvas.SetTextFgColour(owner->GetHighlightFgColour());
  542.         canvas.SetTextBkColour(owner->GetHighlightBkColour());
  543.       }
  544.       else {
  545.         canvas.SetTextFgColour(owner->GetWindowFgColour());
  546.         canvas.SetTextBkColour(owner->GetWindowBkColour());
  547.       }
  548.       canvas.SetPenFgColour(canvas.GetTextBkColour());
  549.       canvas.SetPenBkColour(canvas.GetTextBkColour());
  550.       canvas.SetFillFgColour(canvas.GetTextBkColour());
  551.       canvas.SetFillBkColour(canvas.GetTextBkColour());
  552.       ((PCustomListBox *)item)->OnDrawEntry(dis->itemID,
  553.                      *(PObject *)dis->itemData, canvas, bounds, focus, select);
  554.     }
  555.   }
  556.   return TRUE;
  557. }
  558. BOOL PInteractor::HandleMeasureItem(MEASUREITEMSTRUCT FAR * mis)
  559. {
  560.   if (mis->CtlType != ODT_LISTBOX)
  561.     return FALSE;
  562.   PCustomListBox * listBox =
  563.              (PCustomListBox *)owner->GetWindowObject(GetDlgItem(_hWnd, mis->CtlID));
  564.   if (listBox == NULL)
  565.     return FALSE;
  566.   if (!listBox->IsDescendant(PCustomListBox::Class()))
  567.     return FALSE;
  568.   PDrawCanvas listBoxCanvas(listBox);
  569.   PDim dim = listBoxCanvas.ToPixels(listBox->OnMeasureEntry(mis->itemID,
  570.                                     *(PObject *)mis->itemData, listBoxCanvas));
  571.   mis->itemWidth = dim.Width();
  572.   mis->itemHeight = dim.Height();
  573.   return TRUE;
  574. }
  575. int PInteractor::HandleCompareItem(const COMPAREITEMSTRUCT FAR * cis)
  576. {
  577.   if (cis->CtlType != ODT_LISTBOX)
  578.     return P_MAX_INDEX;
  579.   PInteractor * listBox = owner->GetWindowObject(cis->hwndItem);
  580.   if (listBox == NULL)
  581.     return P_MAX_INDEX;
  582.   if (!listBox->IsDescendant(PCustomListBox::Class()))
  583.     return P_MAX_INDEX;
  584.   PObject * obj1 = (PObject *)cis->itemData1;
  585.   PObject * obj2 = (PObject *)cis->itemData2;
  586.   if (obj1 == NULL || obj2 == NULL)
  587.     return P_MAX_INDEX;
  588.   return obj1->Compare(*obj2);
  589. }
  590. BOOL PInteractor::HandleDeleteItem(const DELETEITEMSTRUCT FAR * dis)
  591. {
  592.   if (dis->CtlType != ODT_LISTBOX)
  593.     return FALSE;
  594.   PListBox * listBox = (PListBox*)owner->GetWindowObject(dis->hwndItem);
  595.   if (listBox == NULL)
  596.     return FALSE;
  597.   if (!listBox->IsDescendant(PCustomListBox::Class()))
  598.     return FALSE;
  599.   if (listBox->deleteObjects)
  600.     delete (PObject *)dis->itemData;
  601.   return TRUE;
  602. }
  603. static PKeyCode KeyFromMouseEvent(UINT event, WPARAM wParam)
  604. {
  605.   switch (event) {
  606.     case WM_MBUTTONDOWN :
  607.     case WM_MBUTTONDBLCLK :
  608.     case WM_MBUTTONUP :
  609.       return PKeyCode(TRUE, wParam, PKeyCode::MiddleButton);
  610.     case WM_RBUTTONDOWN :
  611.     case WM_RBUTTONDBLCLK :
  612.     case WM_RBUTTONUP :
  613.       return PKeyCode(TRUE, wParam, PKeyCode::RightButton);
  614.   }
  615.   return PKeyCode(TRUE, wParam, PKeyCode::LeftButton);
  616. }
  617. BOOL PInteractor::HandleCtlColour(HWND ctlWnd,
  618.                          HDC hDC, const PColour & defFg, const PColour & defBk)
  619. {
  620.   PInteractor * control = owner->GetWindowObject(ctlWnd);
  621.   if (control == NULL)
  622.     return FALSE;
  623.   const PColour & fg = control->GetForegroundColour();
  624.   const PColour & bk = control->GetBackgroundColour();
  625.   if (fg == defFg && bk == defBk)
  626.     return FALSE;
  627.   SetTextColor(hDC, fg.ToCOLORREF());
  628.   SetBkColor(hDC, bk.ToCOLORREF());
  629.   if (control->hBackgroundBrush == NULL)
  630.     control->hBackgroundBrush = CreateSolidBrush(bk.ToCOLORREF());
  631.   _msg->lResult = (LPARAM)control->hBackgroundBrush;
  632.   return TRUE;
  633. }
  634. void PInteractor::WndProc()
  635. {
  636.   switch (_msg->event) {
  637.     case WM_MOUSEMOVE :
  638.       if (PGET_CLASS_VALUE(_hWnd, HCURSOR) == 0)
  639.         SetWndCursor();
  640.       _OnMouseMove(PKeyCode(TRUE, _msg->wParam, PKeyCode::NullValue), PPoint(_msg->lParam));
  641.       return;
  642.     case WM_LBUTTONDOWN :
  643.     case WM_MBUTTONDOWN :
  644.     case WM_RBUTTONDOWN :
  645.       owner->DoBalloonHelp(NULL);
  646.       if (GetCapture() == NULL)
  647.         SetCapture(_hWnd);
  648.       OnMouseDown(KeyFromMouseEvent(_msg->event, _msg->wParam), PPoint(_msg->lParam), FALSE);
  649.       return;
  650.     case WM_LBUTTONDBLCLK :
  651.     case WM_MBUTTONDBLCLK :
  652.     case WM_RBUTTONDBLCLK :
  653.       owner->DoBalloonHelp(NULL);
  654.       OnMouseDown(KeyFromMouseEvent(_msg->event, _msg->wParam), PPoint(_msg->lParam), TRUE);
  655.       return;
  656.     case WM_LBUTTONUP :
  657.     case WM_MBUTTONUP :
  658.     case WM_RBUTTONUP :
  659.       _OnMouseUp(KeyFromMouseEvent(_msg->event, _msg->wParam), PPoint(_msg->lParam));
  660.       if (GetCapture() == _hWnd)
  661.         ReleaseCapture();
  662.       return;
  663.     case WM_KEYDOWN :
  664.       owner->DoBalloonHelp(NULL);
  665.       if (OnKeyDown(PKeyCode(FALSE, _msg->wParam, HIWORD(_msg->lParam)),
  666.                       (_msg->lParam&0x40000000)!=0 ? LOWORD(_msg->lParam) : 0))
  667.         DefWndProc();
  668.       return;
  669.     case WM_KEYUP :
  670.       owner->DoBalloonHelp(NULL);
  671.       OnKeyUp(PKeyCode(FALSE, _msg->wParam, HIWORD(_msg->lParam)));
  672.       return;
  673.     case WM_CHAR :
  674.       OnKeyInput(PString((char)_msg->wParam));
  675.       return;
  676.     case WM_SETFOCUS : {
  677.       caret.Activate(this, caretVisible <= 0);
  678.       OnGainFocus();
  679.       PInteractor * focus = GetFocusInteractor();
  680.       if (focus != this && focus != NULL) {
  681.         if (focus->OnEndInput()) {
  682.           SetFocusInteractor(this);
  683.           OnStartInput();
  684.         }
  685.         else
  686.           focus->GrabFocus();
  687.       }
  688.       break;
  689.     }
  690.     case WM_KILLFOCUS :
  691.       caret.Deactivate(this);
  692.       OnLostFocus();
  693.       break;
  694.     case WM_VSCROLL :
  695.     case WM_HSCROLL :
  696. #if defined(_WIN32)
  697.       if (HandleScrollBar((HWND)_msg->lParam,
  698.                                    LOWORD(_msg->wParam), HIWORD(_msg->wParam)))
  699. #else
  700.       if (HandleScrollBar((HWND)HIWORD(_msg->lParam),
  701.                                       _msg->wParam, (int)LOWORD(_msg->lParam)))
  702. #endif
  703.         return;
  704.       break;
  705.     case WM_COMMAND :
  706.     {
  707.       NMHDR msg;
  708. #if defined(_WIN32)
  709.       msg.hwndFrom = (HWND)_msg->lParam;
  710.       msg.idFrom = LOWORD(_msg->wParam);
  711.       msg.code = HIWORD(_msg->wParam);
  712. #else
  713.       msg.hwndFrom = (HWND)LOWORD(_msg->lParam);
  714.       msg.idFrom = wParam;
  715.       msg.code = HIWORD(_msg->lParam);
  716. #endif
  717.       if (HandleCommand(msg))
  718.         return;
  719.       break;
  720.     }
  721.     case WM_NOTIFY :
  722.       if (HandleCommand(*(LPNMHDR)_msg->lParam))
  723.         return;
  724.       break;
  725.     case WM_DRAWITEM :
  726.       if (HandleDrawItem((const DRAWITEMSTRUCT FAR *)_msg->lParam)) {
  727.         _msg->lResult = TRUE;
  728.         return;
  729.       }
  730.       break;
  731.     case WM_MEASUREITEM :
  732.       if (HandleMeasureItem((MEASUREITEMSTRUCT FAR *)_msg->lParam), _hWnd) {
  733.         _msg->lResult = TRUE;
  734.         return;
  735.       }
  736.       break;
  737.     case WM_COMPAREITEM :
  738.       switch (HandleCompareItem((const COMPAREITEMSTRUCT FAR *)_msg->lParam)) {
  739.         case PObject::LessThan :
  740.           _msg->lResult = -1;
  741.           return;
  742.         case PObject::EqualTo :
  743.           _msg->lResult = 0;
  744.           return;
  745.         case PObject::GreaterThan :
  746.           _msg->lResult = 1;
  747.           return;
  748.       }
  749.       break;
  750.     case WM_DELETEITEM :
  751.       if (HandleDeleteItem((const DELETEITEMSTRUCT FAR *)_msg->lParam)) {
  752.         _msg->lResult = TRUE;
  753.         return;
  754.       }
  755.       break;
  756.     case WM_ERASEBKGND :
  757.       if (PGET_CLASS_VALUE(_hWnd, HBRBACKGROUND) == 0) {
  758.         HBRUSH b = CreateSolidBrush(backgroundColour.ToCOLORREF());
  759.         RECT r;
  760.         GetClientRect(_hWnd, &r);
  761.         FillRect((HDC)_msg->wParam, &r, b);
  762.         DeleteObject(b);
  763.         _msg->lResult = TRUE;
  764.         return;
  765.       }
  766.       break;
  767. #ifdef _WIN32
  768.     case WM_CTLCOLORBTN :
  769.     case WM_CTLCOLORSTATIC :
  770.       if (HandleCtlColour((HWND)_msg->lParam, (HDC)_msg->wParam,
  771.                        owner->GetButtonFgColour(), owner->GetButtonBkColour()))
  772.         return;
  773.       break;
  774.     case WM_CTLCOLORSCROLLBAR :
  775.       if (HandleCtlColour((HWND)_msg->lParam, (HDC)_msg->wParam,
  776.                      owner->GetScrollBarColour(), owner->GetScrollBarColour()))
  777.         return;
  778.       break;
  779.     case WM_CTLCOLOREDIT :
  780.     case WM_CTLCOLORLISTBOX :
  781.       if (HandleCtlColour((HWND)_msg->lParam, (HDC)_msg->wParam,
  782.                        owner->GetWindowFgColour(), owner->GetWindowBkColour()))
  783.         return;
  784.       break;
  785. #else
  786.     case WM_CTLCOLOR :
  787.       switch (HIWORD(_msg->lParam)) {
  788.         case CTLCOLOR_BTN :
  789.           if (HandleCtlColour((HWND)LOWORD(_msg->lParam), (HDC)_msg->wParam,
  790.                        owner->GetButtonFgColour(), owner->GetButtonBkColour()))
  791.             return;
  792.           break;
  793.         case CTLCOLOR_SCROLLBAR :
  794.           if (HandleCtlColour((HWND)LOWORD(_msg->lParam), (HDC)_msg->wParam,
  795.                      owner->GetScrollBarColour(), owner->GetScrollBarColour()))
  796.             return;
  797.           break;
  798.         case CTLCOLOR_EDIT :
  799.         case CTLCOLOR_STATIC :
  800.         case CTLCOLOR_LISTBOX :
  801.           if (HandleCtlColour((HWND)LOWORD(_msg->lParam), (HDC)_msg->wParam,
  802.                        owner->GetWindowFgColour(), owner->GetWindowBkColour()))
  803.             return;
  804.           break;
  805.       }
  806.       break;
  807. #endif
  808.     case WM_PAINT :
  809.       if (_in_WM_PAINT)
  810.         DefWndProc();
  811.       else {
  812.         _in_WM_PAINT = TRUE;
  813.         PRedrawCanvas canvas(this, FALSE);
  814.         OnRedraw(canvas);
  815.         if (canvas.NullHDC())
  816.           DefWndProc();
  817.         _in_WM_PAINT = FALSE;
  818.       }
  819.       return;
  820.     case WM_DESTROY :
  821.       owner->DoBalloonHelp(NULL);
  822.       owner->RemoveWindowHandle(_hWnd);
  823.       RemoveWndFont();
  824.       _hWnd = P_DEAD_WINDOW;
  825.       return;
  826.   }
  827.   DefWndProc();
  828. }
  829. void PInteractor::DefWndProc()
  830. {
  831.   _msg->lResult=DefWindowProc(_hWnd, _msg->event, _msg->wParam, _msg->lParam);
  832.   _msg->processed = FALSE;
  833. }
  834. void PInteractor::OnMouseDown(PKeyCode, const PPoint &, BOOL)
  835. {
  836.   if (GetCapture() == _hWnd)
  837.     ReleaseCapture();
  838.   DefWndProc();
  839. }
  840. void PInteractor::OnMouseUp(PKeyCode, const PPoint &)
  841. {
  842.   DefWndProc();
  843. }
  844. void PInteractor::OnMouseMove(PKeyCode, const PPoint &)
  845. {
  846.   DefWndProc();
  847. }
  848. BOOL PInteractor::OnKeyDown(PKeyCode, unsigned)
  849. {
  850.   return TRUE;
  851. }
  852. void PInteractor::OnKeyUp(PKeyCode key)
  853. {
  854.   DefWndProc();
  855. }
  856. void PInteractor::OnKeyInput(const PString &)
  857. {
  858.   DefWndProc();
  859. }
  860. void PInteractor::OnGainFocus()
  861. {
  862.   DefWndProc();
  863. }
  864. void PInteractor::OnLostFocus()
  865. {
  866.   DefWndProc();
  867. }
  868. void PInteractor::OnRedraw(PCanvas & canvas)
  869. {
  870.   if (canvas.NullHDC() && canvas.IsDescendant(PRedrawCanvas::Class())) {
  871.     DefWndProc();
  872.     canvas.SetHDC(GetDC(_hWnd));
  873.   }
  874. }
  875. void PInteractor::SetWndFont() const
  876. {
  877.   RemoveWndFont();
  878.   HFONT hFont = CreateFont(font.GetHeight(TRUE),
  879.                            0, 0, 0,
  880.                            font.IsBold() ? FW_BOLD : FW_NORMAL,
  881.                            (BYTE)font.IsItalic(),
  882.                            (BYTE)font.IsUnderlined(),
  883.                            0, 0, 0, 0, 0, 0,
  884.                            font.GetFacename());
  885.   PAssertOS(hFont != NULL);
  886.   SendMessage(GetHWND(), WM_SETFONT, (WPARAM)hFont, 0L);
  887.   if ((HFONT)(UINT)SendMessage(GetHWND(), WM_GETFONT, 0, 0L) != hFont)
  888.     DeleteObject(hFont);
  889. }
  890. void PInteractor::RemoveWndFont() const
  891. {
  892.   HFONT hFont = (HFONT)(UINT)SendMessage(GetHWND(), WM_GETFONT, 0, 0L);
  893.   if (hFont == NULL)
  894.     return;
  895.   HWND parWnd = P_DEAD_WINDOW;
  896.   if (GetParent() != NULL)
  897.     parWnd = GetParent()->_hWnd;
  898.   if (parWnd != P_DEAD_WINDOW &&
  899.                   (HFONT)(UINT)SendMessage(parWnd, WM_GETFONT, 0, 0L) == hFont)
  900.     return; // Let parent class delete the hFont
  901.   SendMessage(GetHWND(), WM_SETFONT, NULL, 0L);
  902.   DeleteObject(hFont);
  903. }
  904. void PInteractor::GetCreateWinInfo(WNDCLASS & wndClass)
  905. {
  906.   wndClass.style = CS_HREDRAW|CS_VREDRAW|CS_DBLCLKS;
  907.   wndClass.lpfnWndProc = owner->GetWndProcPtr(PApplication::WndProcType);
  908.   wndClass.cbClsExtra = 0;
  909.   wndClass.cbWndExtra = 0;
  910.   wndClass.hInstance = owner->GetInstance();
  911.   wndClass.hIcon = NULL;
  912.   wndClass.hCursor = NULL;
  913.   wndClass.hbrBackground = NULL;
  914.   wndClass.lpszMenuName = NULL;
  915.   wndClass.lpszClassName = GetClass();
  916.   _styleBits = WS_CHILD|WS_CLIPCHILDREN|WS_CLIPSIBLINGS;
  917.   _exStyleBits = WS_EX_NOPARENTNOTIFY;
  918. }
  919. PINDEX PInteractor::GetNumChildren()
  920. {
  921.   if (_hWnd == NULL)
  922.     GetHWND();
  923.   return children.GetSize();
  924. }
  925. HWND PInteractor::GetHWND() const
  926. {
  927.   if (_hWnd == NULL) {
  928.     if (PThread::Current() == owner)
  929.       ((PInteractor*)this)->CreateHWND();
  930.     else {
  931.       // All windows must be created in the main thread, so go to stupid
  932.       // lengths to make sure it happens
  933.       owner->windowsMutex.Wait();
  934.       owner->delayedCreateInteractors.Append((PInteractor*)this);
  935.       owner->windowsMutex.Signal();
  936.       // Post a message to unblock the main loop, so can process above.
  937.       ::PostThreadMessage(owner->GetThreadId(), WM_USER, 0, 0);
  938.       // Wait for main loop thread to do the job.
  939.       owner->delayedCreateInteractorsDone.Wait();
  940.     }
  941.   }
  942.   if (_hWnd != NULL && _hWnd != P_DEAD_WINDOW)
  943.     return _hWnd;
  944.   PAssertAlways(PInvalidWindow);
  945.   return NULL;
  946. }
  947. void PInteractor::CreateHWND()
  948. {
  949.   PAssert(parent != NULL ||
  950.                IsDescendant(PTopLevelWindow::Class()), "Window has no parent");
  951.   HINSTANCE hInst = owner->GetInstance();
  952.   WNDCLASS wclass;
  953.   GetCreateWinInfo(wclass);
  954.   if (!GetClassInfo(hInst, wclass.lpszClassName, &wclass))
  955.     PAssertOS(RegisterClass(&wclass));
  956.   _hWnd = CreateWindowEx(_exStyleBits, wclass.lpszClassName, "", _styleBits,
  957.                          CW_USEDEFAULT, CW_USEDEFAULT,
  958.                          CW_USEDEFAULT, CW_USEDEFAULT,
  959.                          parent != NULL ? parent->GetHWND() : NULL,
  960.                          NULL, hInst, NULL);
  961.   owner->AddWindowHandle(PAssertNULL(_hWnd), this);
  962.   SetWndFont();
  963. }
  964. PString PInteractor::GetWndText(UINT lenMsg,
  965.                            UINT getMsg,WPARAM wParamGet, WPARAM wParamLen) const
  966. {
  967.   PString title;
  968.   HWND hWnd = GetHWND();
  969.   UINT len = (UINT)SendMessage(hWnd, lenMsg, wParamLen, 0L)+1;
  970.   if (len < sizeof(UINT))
  971.     len = sizeof(UINT);
  972.   char * ptr = title.GetPointer(len);
  973.   if (wParamGet == (WPARAM)-1)
  974.     wParamGet = len;
  975.   else
  976.     *(UINT *)ptr = len;
  977.   SendMessage(hWnd, getMsg, wParamGet, (DWORD)(LPSTR)ptr);
  978.   PINDEX pos;
  979.   while ((pos = title.Find("rn")) != P_MAX_INDEX)
  980.     title.Delete(pos, 1);
  981.   return title;
  982. }
  983. //////////////////////////////////////////////////////////////////////////////
  984. PTitledWindow::PTitledWindow(PInteractor * par, unsigned CanDo)
  985.   : PInteractor(par),
  986.     icon(PSTD_ID_ICON_WINDOW)
  987. {
  988.   focusInteractor = this;
  989.   initFlags = CanDo;
  990. }
  991. PTitledWindow::PTitledWindow(unsigned CanDo)
  992.   : icon(PSTD_ID_ICON_WINDOW)
  993. {
  994.   focusInteractor = this;
  995.   initFlags = CanDo;
  996. }
  997. void PTitledWindow::GetCreateWinInfo(WNDCLASS & wndClass)
  998. {
  999.   PInteractor::GetCreateWinInfo(wndClass);
  1000.   if ((initFlags&CanClose) == 0)
  1001.     wndClass.style |= CS_NOCLOSE;
  1002.   wndClass.hIcon = icon.GetHICON();
  1003.   if ((initFlags&CanGrow) != 0)
  1004.     _styleBits |= WS_THICKFRAME;
  1005.   if ((initFlags&CanIconify) != 0)
  1006.     _styleBits |= WS_MINIMIZEBOX;
  1007.   if ((initFlags&CanZoom) != 0)
  1008.     _styleBits |= WS_MAXIMIZEBOX;
  1009.   _styleBits |= WS_CAPTION|WS_SYSMENU;
  1010. }
  1011. void PTitledWindow::WndProc()
  1012. {
  1013.   switch (_msg->event) {
  1014.     case WM_CLOSE :
  1015.       Close();
  1016.       return;
  1017.     case WM_DESTROY :
  1018.       OnClose();
  1019.       break;
  1020.     case WM_SETFOCUS :
  1021.       if (GetFocusInteractor() != this) {
  1022.         GetFocusInteractor()->GrabFocus();
  1023.         DefWndProc();
  1024.         return;
  1025.       }
  1026.       break;
  1027.     case WM_NCACTIVATE :
  1028.       if (_msg->wParam == FALSE && owner->balloon != NULL) {
  1029.         _msg->lResult = 0;
  1030.         return;
  1031.       }
  1032.       break;
  1033.     case WM_ACTIVATE :
  1034.       OnActivate(LOWORD(_msg->wParam) != WA_INACTIVE);
  1035.       break;
  1036.     case WM_MDIACTIVATE :
  1037.       OnActivate((HWND)(UINT)_msg->lParam == _hWnd);
  1038.       break;
  1039.     case WM_MOVE :
  1040.       OnReposition(PPoint(_msg->lParam));
  1041.       break;
  1042.     case WM_SIZE :
  1043.       if (IsWindowVisible(_hWnd))
  1044.         OnResize(PDim::FromDWORD(_msg->lParam),
  1045.                  _msg->wParam == SIZE_MINIMIZED ? Iconic :
  1046.                  _msg->wParam == SIZE_MAXIMIZED ? Zoomed : Normalised);
  1047.       break;
  1048.     case WM_GETMINMAXINFO :
  1049.       MINMAXINFO * mmi = (MINMAXINFO *)_msg->lParam;
  1050.       PRect client;
  1051.       GetClientRect(GetHWND(), client);
  1052.       PRect structure = client;
  1053.       AdjustWindowRectEx(structure, _styleBits,
  1054.                          IsDescendant(PTopLevelWindow::Class()) &&
  1055.                                   ((PTopLevelWindow *)this)->GetMenu() != NULL,
  1056.                          _exStyleBits);
  1057.       PDim adjust = structure.Dimensions() - client.Dimensions();
  1058.       if (minSize.Width() != 0 && minSize.Height() != 0) {
  1059.         mmi->ptMinTrackSize.x = minSize.Width() + adjust.Width();
  1060.         mmi->ptMinTrackSize.y = minSize.Height() + adjust.Height();
  1061.       }
  1062.       if (maxSize.Width() != 0 && maxSize.Height() != 0) {
  1063.         mmi->ptMaxTrackSize.x = maxSize.Width() + adjust.Width();
  1064.         mmi->ptMaxTrackSize.y = maxSize.Height() + adjust.Height();
  1065.       }
  1066.       if (zoomSize.Width() != 0 && zoomSize.Height() != 0) {
  1067.         mmi->ptMaxSize.x = zoomSize.Width() + adjust.Width();
  1068.         mmi->ptMaxSize.y = zoomSize.Height() + adjust.Height();
  1069.       }
  1070.       break;
  1071.   }
  1072.   PInteractor::WndProc();
  1073. }
  1074. void PTitledWindow::SetMinSize(const PDim & dim, CoordinateSystem coords)
  1075. {
  1076.   if (coords != LocalCoords)
  1077.     minSize = dim;
  1078.   else
  1079.     minSize = ToPixels(dim);
  1080.   SetDimensions(GetDimensions(PixelCoords), PixelCoords);
  1081. }
  1082. void PTitledWindow::SetMaxSize(const PDim & dim, CoordinateSystem coords)
  1083. {
  1084.   if (coords != LocalCoords)
  1085.     maxSize = dim;
  1086.   else
  1087.     maxSize = ToPixels(dim);
  1088.   SetDimensions(GetDimensions(PixelCoords), PixelCoords);
  1089. }
  1090. void PTitledWindow::SetIcon(const PIcon & icn)
  1091. {
  1092.   PSET_CLASS_VALUE(GetHWND(), HICON, icn.GetHICON());
  1093.   icon = icn;
  1094. }
  1095. void PTitledWindow::OnReposition(const PPoint &)
  1096. {
  1097.   DefWndProc();
  1098. }
  1099. void PTitledWindow::OnActivate(BOOL)
  1100. {
  1101.   DefWndProc();
  1102. }
  1103. void PTitledWindow::OnResize(const PDim &, ResizeType)
  1104. {
  1105.   DefWndProc();
  1106. }
  1107. //////////////////////////////////////////////////////////////////////////////
  1108. PTopLevelWindow::PTopLevelWindow(unsigned CanDo)
  1109.   : PTitledWindow(CanDo),
  1110.     helpMenu(PResourceString(PSTD_ID_STR_HELP_MENU, "&Help"))
  1111. {
  1112.   menu = NULL;
  1113.   deleteMenu = FALSE;
  1114.   if (owner->mainWindow == NULL)
  1115.     owner->mainWindow = this;
  1116.   SetTitle(owner->GetName());
  1117.   SetMenu(NULL);
  1118.   new PMenuItem(PSTD_ID_MENU_HELP_CONTENTS, helpMenu,
  1119.                       PResourceString(PSTD_ID_STR_HELP_CONTENTS, "&Contents"));
  1120.   new PMenuItem(PSTD_ID_STR_HELP_SEARCH, helpMenu,
  1121.               PResourceString(PSTD_ID_STR_HELP_SEARCH, "&Search for Help..."));
  1122.   new PMenuItem(PSTD_ID_MENU_HELP_ON_HELP, helpMenu,
  1123.                 PResourceString(PSTD_ID_STR_HELP_ON_HELP, "&How to Use Help"));
  1124.   new PMenuSeparator(helpMenu);
  1125.   new PMenuItem(PSTD_ID_MENU_ABOUT, helpMenu, owner->GetAboutMenuItemString());
  1126. }
  1127. PTopLevelWindow::~PTopLevelWindow()
  1128. {
  1129.   if (deleteMenu)
  1130.     delete menu;
  1131.   if (owner->mainWindow == this)
  1132.     owner->mainWindow = NULL;
  1133. }
  1134. void PTopLevelWindow::WndProc()
  1135. {
  1136.   switch (_msg->event) {
  1137.     case WM_SYSCOMMAND :
  1138.       if (_msg->wParam == PSTD_ID_MENU_ABOUT) {
  1139.         owner->OnAbout();
  1140.         return;
  1141.       }
  1142.       break;
  1143.     case WM_COMMAND :
  1144.       switch (_msg->wParam) {
  1145.         case PSTD_ID_MENU_ABOUT :
  1146.           owner->OnAbout();
  1147.           return;
  1148.         case PSTD_ID_MENU_HELP_CONTENTS :
  1149.           owner->DoContextHelp(PSTD_ID_HELP_CONTENTS);
  1150.           return;
  1151.         case PSTD_ID_MENU_HELP_SEARCH :
  1152.           owner->DoContextHelp(PSTD_ID_HELP_SEARCH);
  1153.           return;
  1154.         case PSTD_ID_MENU_HELP_ON_HELP :
  1155.           owner->DoContextHelp(PSTD_ID_HELP_ON_HELP);
  1156.           return;
  1157.         default :
  1158.           if (menu != NULL &&
  1159. #if defined(_WIN32)
  1160.                               _msg->lParam == 0)
  1161. #else
  1162.                               LOWORD(_msg->lParam) == 0)
  1163. #endif
  1164.           {
  1165.             PMenuItem*item=menu->GetItemFromKey((PRESOURCE_ID)LOWORD(_msg->wParam));
  1166.             if (item != NULL) {
  1167.               OnMenuItemSelect(*item);
  1168.               return;
  1169.             }
  1170.           }
  1171.       }
  1172.       break;
  1173.     case WM_INITMENU :
  1174.       if (_msg->wParam != 0 && menu != NULL) {
  1175.         OnMenuStartSelect();
  1176.         return;
  1177.       }
  1178.       break;
  1179.   }
  1180.   PTitledWindow::WndProc();
  1181. }
  1182. void PTopLevelWindow::GetCreateWinInfo(WNDCLASS & wndClass)
  1183. {
  1184.   PTitledWindow::GetCreateWinInfo(wndClass);
  1185.   _styleBits &= ~WS_CHILD;
  1186. }
  1187. //////////////////////////////////////////////////////////////////////////////
  1188. PMDIFrameWindow::PMDIFrameWindow(unsigned CanDo)
  1189.   : PTopLevelWindow(CanDo),
  1190.     windowMenu(PResourceString(PSTD_ID_STR_WINDOW_MENU, "&Window"))
  1191. {
  1192.   CLIENTCREATESTRUCT ccs;
  1193.   ccs.hWindowMenu = windowMenu.GetHMENU();
  1194.   ccs.idFirstChild = 32000;
  1195.   mdiClient = CreateWindow("MDICLIENT", "",
  1196.        WS_CHILD|WS_CLIPCHILDREN|WS_CLIPSIBLINGS|WS_VISIBLE|MDIS_ALLCHILDSTYLES,
  1197.        0, 0, 0, 0, GetHWND(), NULL, owner->GetInstance(), &ccs);
  1198.   PAssertNULL(mdiClient);
  1199.   owner->mdiClient = mdiClient;
  1200.   backgroundColour.FromSYSCOLOR(COLOR_APPWORKSPACE);
  1201.   new PMenuItem(PSTD_ID_MENU_WINDOW_CASCADE, windowMenu,
  1202.                       PResourceString(PSTD_ID_STR_WINDOW_CASCADE, "&Cascade"));
  1203.   new PMenuItem(PSTD_ID_MENU_WINDOW_TILE, windowMenu,
  1204.                             PResourceString(PSTD_ID_STR_WINDOW_TILE, "&Tile"));
  1205.   new PMenuItem(PSTD_ID_MENU_WINDOW_ARRANGE, windowMenu,
  1206.                 PResourceString(PSTD_ID_STR_WINDOW_ARRANGE, "&Arrange Icons"));
  1207. }
  1208. PMDIDocWindow * PMDIFrameWindow::GetActiveDocument()
  1209. {
  1210.   HWND hChild = (HWND)(UINT)SendMessage(mdiClient, WM_MDIGETACTIVE, 0, 0L);
  1211.   if (hChild == NULL)
  1212.     return NULL;
  1213.   PInteractor * window = owner->GetWindowObject(hChild);
  1214.   return (PMDIDocWindow *)PAssertNULL(window);
  1215. }
  1216. void PMDIFrameWindow::SetDocumentArea(const PRect & rect,
  1217.                                       CoordinateSystem coords)
  1218. {
  1219.   switch (coords) {
  1220.     case LocalCoords :
  1221.       documentArea = ToPixels(rect);
  1222.       break;
  1223.     case PixelCoords :
  1224.       documentArea = rect;
  1225.       break;
  1226.     case ScreenCoords :
  1227.       PPoint origin = rect.Origin();
  1228.       ClientToScreen(GetHWND(), origin);
  1229.       documentArea = rect;
  1230.       documentArea.SetOrigin(origin);
  1231.   }
  1232.   PRect r = documentArea;
  1233.   if (documentArea.IsEmpty())
  1234.     r = GetDimensions(PixelCoords);
  1235.   SetWindowPos(mdiClient, HWND_BOTTOM,
  1236.                           r.X(), r.Y(), r.Width(), r.Height(), SWP_NOACTIVATE);
  1237. }
  1238. void PMDIFrameWindow::WndProc()
  1239. {
  1240.   switch (_msg->event) {
  1241.     case WM_COMMAND :
  1242.       switch (_msg->wParam) {
  1243.         case PSTD_ID_MENU_WINDOW_CASCADE :
  1244.           CascadeDocuments();
  1245.           return;
  1246.         case PSTD_ID_MENU_WINDOW_TILE :
  1247.           TileDocuments(GetKeyState(VK_SHIFT) < 0);
  1248.           return;
  1249.         case PSTD_ID_MENU_WINDOW_ARRANGE :
  1250.           ArrangeIcons();
  1251.           return;
  1252.       }
  1253.       break;
  1254.     case WM_SIZE :
  1255.       PTopLevelWindow::WndProc();
  1256.       SetDocumentArea(documentArea, PixelCoords);
  1257.       return;
  1258.   }
  1259.   PTopLevelWindow::WndProc();
  1260. }
  1261. void PMDIFrameWindow::DefWndProc()
  1262. {
  1263.   _msg->lResult = DefFrameProc(_hWnd,
  1264.                            mdiClient, _msg->event, _msg->wParam, _msg->lParam);
  1265. }
  1266. ///////////////////////////////////////////////////////////////////////////////
  1267. // PMDIDocWindow
  1268. PMDIDocWindow::~PMDIDocWindow()
  1269. {
  1270.   if (_hWnd != NULL && _hWnd != P_DEAD_WINDOW)
  1271.     SendMessage(((PMDIFrameWindow*)GetParent())->mdiClient,
  1272.                                              WM_MDIDESTROY, (WPARAM)_hWnd, 0L);
  1273. }
  1274. void PMDIDocWindow::CreateHWND()
  1275. {
  1276.   PAssert(parent->IsDescendant(PMDIFrameWindow::Class()), "Bad MDI parent");
  1277.   HINSTANCE hInst = owner->GetInstance();
  1278.   WNDCLASS wclass;
  1279.   MDICREATESTRUCT mcs;
  1280.   GetCreateWinInfo(wclass);
  1281.   mcs.style = _styleBits;
  1282.   mcs.szClass = wclass.lpszClassName;
  1283.   mcs.szTitle = initialTitle;
  1284.   mcs.hOwner = hInst;
  1285.   mcs.x = mcs.y = mcs.cx = mcs.cy = CW_USEDEFAULT;
  1286.   mcs.lParam = 0;
  1287.   if (!GetClassInfo(hInst, wclass.lpszClassName, &wclass))
  1288.     PAssertOS(RegisterClass(&wclass));
  1289. #if defined(_WIN32)
  1290.   _hWnd = CreateMDIWindow((LPTSTR)mcs.szClass, (LPTSTR)mcs.szTitle,
  1291.                           mcs.style, mcs.x, mcs.y, mcs.cx, mcs.cy,
  1292.                           ((PMDIFrameWindow *)parent)->mdiClient,
  1293.                           hInst, mcs.lParam);
  1294. #else
  1295.   _hWnd = (HWND)(UINT)SendMessage(((PMDIFrameWindow *)parent)->mdiClient,
  1296.                                   WM_MDICREATE, 0, (LPARAM)&mcs);
  1297. #endif
  1298.   owner->AddWindowHandle(PAssertNULL(_hWnd), this);
  1299.   SetWndFont();
  1300. }
  1301. void PMDIDocWindow::DefWndProc()
  1302. {
  1303.   _msg->lResult = DefMDIChildProc(_hWnd,_msg->event,_msg->wParam,_msg->lParam);
  1304. }
  1305. void PMDIDocWindow::Show(BOOL visible)
  1306. {
  1307.   ShowWindow(GetHWND(), visible ? SW_SHOW : SW_HIDE);
  1308. #if defined(_WIN32)
  1309.   SendMessage(((PMDIFrameWindow *)parent)->mdiClient,WM_MDIREFRESHMENU, 0, 0L);
  1310. #else  
  1311.   SendMessage(((PMDIFrameWindow *)parent)->mdiClient, WM_MDISETMENU, TRUE, 0L);
  1312. #endif
  1313.   PDim dim = GetDimensions(PixelCoords);
  1314.   PInteractor::_WindowsMessage * oldMsg = _msg;
  1315.   PInteractor::_WindowsMessage message;
  1316.   message.event = WM_SIZE;
  1317.   message.wParam = SIZE_RESTORED;
  1318.   message.lParam = dim.ToDWORD();
  1319.   message.lResult = 0;
  1320.   message.processed = TRUE;
  1321.   _msg = &message;
  1322.   OnResize(dim, Normalised);
  1323.   _msg = oldMsg;
  1324. }
  1325. void PMDIDocWindow::Activate()
  1326. {
  1327.   if (!IsVisible())
  1328.     Show();
  1329.   SendMessage(((PMDIFrameWindow*)parent)->mdiClient,
  1330.                                        WM_MDIACTIVATE, (WPARAM)GetHWND(), 0L);
  1331. }
  1332. void PMDIDocWindow::SetTitle(const PString & title)
  1333. {
  1334.   PTitledWindow::SetTitle(title);
  1335. #if defined(_WIN32)
  1336.   SendMessage(((PMDIFrameWindow *)parent)->mdiClient,WM_MDIREFRESHMENU, 0, 0L);
  1337. #else  
  1338.   SendMessage(((PMDIFrameWindow *)parent)->mdiClient, WM_MDISETMENU, TRUE, 0L);
  1339. #endif
  1340. }
  1341. ///////////////////////////////////////////////////////////////////////////////
  1342. // PPopUp
  1343. PPopUp::PPopUp(PInteractor * parent)
  1344.   : PInteractor(parent)
  1345. {
  1346. }
  1347. void PPopUp::GetCreateWinInfo(WNDCLASS & wndClass)
  1348. {
  1349.   PInteractor::GetCreateWinInfo(wndClass);
  1350.   wndClass.style = CS_HREDRAW|CS_VREDRAW|CS_SAVEBITS;
  1351.   _styleBits = WS_POPUP|WS_BORDER|WS_DISABLED;
  1352.   _exStyleBits |= WS_EX_TOPMOST;
  1353. }
  1354. void PPopUp::WndProc()
  1355. {
  1356.   switch (_msg->event) {
  1357.     case WM_SETFOCUS :
  1358.     case WM_MOUSEMOVE :
  1359.       return;
  1360.   }
  1361.   PInteractor::WndProc();
  1362. }
  1363. // End Of File ///////////////////////////////////////////////////////////////