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

IP电话/视频会议

开发平台:

Visual C++

  1. /*
  2.  * misc.cxx
  3.  *
  4.  * Miscellaneous GUI class 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: misc.cxx,v $
  30.  * Revision 1.66  2000/03/17 20:32:22  robertj
  31.  * Fixed race conditions in mult-threaded windows (dialogs in particular)
  32.  *
  33.  * Revision 1.65  2000/03/04 07:50:05  robertj
  34.  * Fixed problem with window not appearing when assert on GUI based win32 apps.
  35.  *
  36.  * Revision 1.64  1999/11/06 05:13:47  robertj
  37.  * Fixed reporting of memory leak that isn't for debug/trace stream.
  38.  *
  39.  * Revision 1.63  1999/10/24 11:52:05  robertj
  40.  * Fixed problems with creating/deleting dialogs from background threads.
  41.  *
  42.  * Revision 1.62  1999/08/17 03:46:42  robertj
  43.  * Fixed usage of inlines in optimised version.
  44.  *
  45.  * Revision 1.61  1999/08/07 07:13:23  robertj
  46.  * Fixed problems with "balloon help" text popup.
  47.  *
  48.  * Revision 1.60  1999/06/14 07:59:39  robertj
  49.  * Enhanced tracing again to add options to trace output (timestamps etc).
  50.  *
  51.  * Revision 1.59  1999/02/22 10:11:06  robertj
  52.  * Added trace stream output to debug output stream.
  53.  *
  54.  * Revision 1.58  1998/12/12 00:45:44  robertj
  55.  * new directory structure
  56.  *
  57.  * Revision 1.57  1998/11/30 04:49:50  robertj
  58.  * New directory structure
  59.  *
  60.  * Revision 1.56  1998/10/13 14:14:41  robertj
  61.  * Complete rewrite of memory leak detection code.
  62.  *
  63.  * Revision 1.55  1998/09/24 03:42:53  robertj
  64.  * Added open software license.
  65.  *
  66.  * Revision 1.54  1998/04/07 13:31:34  robertj
  67.  * Changed startup code to support PApplication class.
  68.  *
  69.  * Revision 1.53  1998/03/09 01:34:53  robertj
  70.  * Changed "system" font to not be the system font, WIn95 weirdness.
  71.  *
  72.  * Revision 1.52  1997/07/08 12:56:31  robertj
  73.  * DLL support
  74.  *
  75.  * Revision 1.51  1997/04/27 05:50:34  robertj
  76.  * DLL support.
  77.  *
  78.  * Revision 1.50  1996/10/31 12:39:57  robertj
  79.  * Added RCS keywords.
  80.  *
  81.  */
  82. #include <pwlib.h>
  83. #include <ptlibdebstrm.h>
  84. #if !P_USE_INLINES
  85. #include <pwlibpwlib.inl>
  86. #endif
  87. #define new PNEW
  88. //
  89. // If we are building with Win95/NT4 headers, we need to declare
  90. // the multimonitor-related metrics ourselves.
  91. //
  92. #ifndef SM_CMONITORS
  93. #define SM_XVIRTUALSCREEN       76
  94. #define SM_YVIRTUALSCREEN       77
  95. #define SM_CXVIRTUALSCREEN      78
  96. #define SM_CYVIRTUALSCREEN      79
  97. #define SM_CMONITORS            80
  98. #define SM_SAMEDISPLAYFORMAT    81
  99. #endif
  100. ///////////////////////////////////////////////////////////////////////////////
  101. // PKeyCode
  102. PKeyCode::PKeyCode(BOOL mouseMessage, WPARAM wParam, int other)
  103. {
  104.   if (mouseMessage) {
  105.     value = (Value)other;
  106.     modifiers = NoModifier;
  107.     if ((wParam&MK_CONTROL) != 0)
  108.       modifiers = (Modifiers)(modifiers|Control);
  109.     if ((wParam&MK_SHIFT) != 0)
  110.       modifiers = (Modifiers)(modifiers|Shift);
  111.     if ((wParam&MK_LBUTTON) != 0)
  112.       modifiers = (Modifiers)(modifiers|LeftMouseButton);
  113.     if ((wParam&MK_RBUTTON) != 0)
  114.       modifiers = (Modifiers)(modifiers|RightMouseButton);
  115.   }
  116.   else {
  117.     static Value fromVK[] = { 
  118.       NullValue, LeftButton, RightButton, Cancel, MiddleButton, NullValue,
  119.       NullValue, NullValue, BackSpace, Tab, NullValue, NullValue, Clear,
  120.       Return, NullValue, NullValue, ShiftKey, ControlKey, Altkey, Oem1,
  121.       CapsLockKey, NullValue, NullValue, NullValue, NullValue, NullValue,
  122.       NullValue, Escape, NullValue, NullValue, NullValue, NullValue, Space,
  123.       PageUp, PageDown, End, Home, Left, Up, Right, Down, Oem2, Oem3,
  124.       Oem4, Oem5, Insert, Delete, Help, KB0, KB1, KB2, KB3, KB4,
  125.       KB5, KB6, KB7, KB8, KB9, NullValue, NullValue, NullValue, NullValue,
  126.       NullValue, NullValue, NullValue, A, B, C, D, E, F, G, H, I, J, K, L, M,
  127.       N, O, P, Q, R, S, T, U, V, W, X, Y, Z, NullValue, NullValue, NullValue,
  128.       NullValue, NullValue, KP0, KP1, KP2, KP3, KP4, KP5, KP6, KP7, KP8, KP9,
  129.       Multiply, Add, Separator, Subtract, Decimal, Divide, F1, F2, F3, F4,
  130.       F5, F6, F7, F8, F9, F10, F11, F12, F13, F14, F15, F16, F17, F18, F19,
  131.       F20, F21, F22, F23, F24, NullValue, NullValue, NullValue, NullValue,
  132.       NullValue, NullValue, NullValue, NullValue, Oem6, Oem7,
  133.       NullValue, NullValue, NullValue, NullValue, NullValue, NullValue, //97
  134.       NullValue, NullValue, NullValue, NullValue, NullValue, NullValue, //9E
  135.       NullValue, NullValue, NullValue, NullValue, NullValue, NullValue, //A5
  136.       NullValue, NullValue, NullValue, NullValue, NullValue, NullValue, //AB
  137.       NullValue, NullValue, NullValue, NullValue, NullValue, NullValue, //B1
  138.       NullValue, NullValue, NullValue, NullValue, NullValue, NullValue, //B8
  139.       NullValue, Oem8, Oem10, Oem11, Oem12, Oem13, Oem14, Oem15,
  140.       NullValue, NullValue, NullValue, NullValue, NullValue, NullValue, //C6
  141.       NullValue, NullValue, NullValue, NullValue, NullValue, NullValue, //CC
  142.       NullValue, NullValue, NullValue, NullValue, NullValue, NullValue, //D2
  143.       NullValue, NullValue, NullValue, NullValue, NullValue, NullValue, //D8
  144.       NullValue, NullValue, Oem16, Oem17, Oem18, Oem19, Oem20, Oem21, //E0
  145.       Oem22, Oem23, Oem24, Oem25, NullValue, Oem26, NullValue, //E7
  146.       NullValue, Oem27, Oem28, Oem29, Oem30, Oem31, Oem32, Oem33, Oem34, //F0
  147.       Oem35, Oem36, Oem37, Oem38, Oem39
  148.     };
  149.     value = wParam < PARRAYSIZE(fromVK) ? fromVK[wParam] : NullValue;
  150.     modifiers = NoModifier;
  151.   }
  152. }
  153. WORD PKeyCode::VKCode()
  154. {
  155.   static WORD toVK[LastCode] = { 
  156.     0, VK_LBUTTON, VK_RBUTTON, VK_MBUTTON,
  157.     'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
  158.     'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
  159.     '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
  160.     VK_NUMPAD0, VK_NUMPAD1, VK_NUMPAD2, VK_NUMPAD3, VK_NUMPAD4,
  161.     VK_NUMPAD5, VK_NUMPAD6, VK_NUMPAD7, VK_NUMPAD8, VK_NUMPAD9,
  162.     VK_ADD, VK_SUBTRACT, VK_MULTIPLY, VK_DIVIDE, VK_SEPARATOR, VK_DECIMAL,    
  163.     VK_F1, VK_F2, VK_F3, VK_F4, VK_F5, VK_F6, VK_F7, VK_F8,
  164.     VK_F9, VK_F10, VK_F11, VK_F12, VK_F13, VK_F14, VK_F15, VK_F16,
  165.     VK_F17, VK_F18, VK_F19, VK_F20, VK_F21, VK_F22, VK_F23, VK_F24, 
  166.     VK_UP, VK_DOWN, VK_LEFT, VK_RIGHT, VK_PRIOR, VK_NEXT, VK_HOME, VK_END,
  167.     VK_INSERT, VK_DELETE, VK_F20, VK_F21, VK_F22, VK_F23,
  168.     VK_CLEAR, VK_CANCEL, VK_HELP, VK_F24,
  169.     VK_BACK, VK_TAB, VK_RETURN, VK_ESCAPE, VK_SPACE,
  170.     VK_CAPITAL, VK_SHIFT, VK_CONTROL, VK_MENU, VK_CONTROL, VK_MENU, VK_MENU,
  171.     VK_PAUSE, VK_SELECT, 0x2a, VK_EXECUTE, VK_SNAPSHOT, VK_NUMLOCK, VK_SCROLL,
  172.     0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
  173.     0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe6, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee,
  174.     0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5
  175.   };
  176.   PAssert(value < LastCode, "Bad key code");
  177.   return toVK[value];
  178. }
  179. WORD PKeyCode::MouseModifiers()
  180. {
  181.   WORD mm = 0;
  182.   if (IsModifier(Control))
  183.     mm |= MK_CONTROL;
  184.   if (IsModifier(Shift))
  185.     mm |= MK_SHIFT;
  186.   if (IsModifier(LeftMouseButton))
  187.     mm |= MK_LBUTTON;
  188.   if (IsModifier(RightMouseButton))
  189.     mm |= MK_RBUTTON;
  190.   return mm;
  191. }
  192. ///////////////////////////////////////////////////////////////////////////////
  193. // PResourceData
  194. PResourceData::PResourceData(const PString & resType, PRESOURCE_ID resID)
  195. {
  196.   HINSTANCE hInst = PApplication::Current().GetInstance();
  197.   HRSRC hRes = FindResource(hInst, MAKEINTRESOURCE(resID), resType);
  198.   hResource = LoadResource(hInst, PAssertNULL(hRes));
  199.   lpResource = (LPSTR)LockResource(PAssertNULL(hResource));
  200.   reference->size = 0; //(PINDEX)GlobalSize(hResource);
  201. }
  202. void PResourceData::CopyContents(const PResourceData & res)
  203. {
  204.   hResource = res.hResource;
  205.   lpResource = res.lpResource;
  206. }
  207. PObject::Comparison PResourceData::Compare(const PObject & obj) const
  208. {
  209.   PAssert(obj.IsDescendant(PResourceData::Class()), PInvalidCast);
  210.   return hResource == ((const PResourceData &)obj).hResource
  211.                                                       ? EqualTo : GreaterThan;
  212. }
  213. BOOL PResourceData::SetSize(PINDEX)
  214. {
  215.   return TRUE;
  216. }
  217. void PResourceData::DestroyContents()
  218. {
  219.   if (hResource != NULL) {
  220.     UnlockResource(hResource);
  221.     FreeResource(hResource);
  222.     hResource = NULL;
  223.   }
  224. }
  225. ///////////////////////////////////////////////////////////////////////////////
  226. // PResourceString
  227. void PResourceString::Construct(PRESOURCE_ID resID)
  228. {
  229.   PINDEX sz = 100;
  230.   do {
  231.     sz *= 2;
  232.   } while (LoadString(PApplication::Current().GetInstance(),
  233.                                            resID, GetPointer(sz+1), sz) >= sz);
  234.   MakeMinimumSize();
  235. }
  236. ///////////////////////////////////////////////////////////////////////////////
  237. // PCursor
  238. PCursor::PCursor(PRESOURCE_ID resID)
  239. {
  240.   deleteCursor = FALSE;
  241.   switch ((unsigned)resID) {
  242.     case PSTD_ID_CURSOR_ARROW :
  243.       hCursor = LoadCursor(NULL, IDC_ARROW);
  244.       break;
  245.     case PSTD_ID_CURSOR_IBEAM :
  246.       hCursor = LoadCursor(NULL, IDC_IBEAM);
  247.       break;
  248.     case PSTD_ID_CURSOR_WAIT :
  249.       hCursor = LoadCursor(NULL, IDC_WAIT);
  250.       break;
  251.     case PSTD_ID_CURSOR_CROSS :
  252.       hCursor = LoadCursor(NULL, IDC_CROSS);
  253.       break;
  254.     case PSTD_ID_CURSOR_MOVELEFT :
  255.     case PSTD_ID_CURSOR_MOVERIGHT :
  256.     case PSTD_ID_CURSOR_LEFTRIGHT :
  257.       hCursor = LoadCursor(NULL, IDC_SIZEWE);
  258.       break;
  259.     case PSTD_ID_CURSOR_MOVETOP :
  260.     case PSTD_ID_CURSOR_MOVEBOTTOM :
  261.     case PSTD_ID_CURSOR_UPDOWN :
  262.       hCursor = LoadCursor(NULL, IDC_SIZENS);
  263.       break;
  264.     case PSTD_ID_CURSOR_MOVETOPRIGHT :
  265.     case PSTD_ID_CURSOR_MOVEBOTLEFT :
  266.       hCursor = LoadCursor(NULL, IDC_SIZENESW);
  267.       break;
  268.     case PSTD_ID_CURSOR_MOVETOPLEFT :
  269.     case PSTD_ID_CURSOR_MOVEBOTRIGHT :
  270.       hCursor = LoadCursor(NULL, IDC_SIZENWSE);
  271.       break;
  272.     default :
  273.       hCursor = LoadCursor(PApplication::Current().GetInstance(),
  274.                                                       MAKEINTRESOURCE(resID));
  275.       deleteCursor = TRUE;
  276.   }
  277.   PAssertOS(hCursor != NULL);
  278. }
  279. PObject::Comparison PCursor::Compare(const PObject & obj) const
  280. {
  281.   PAssert(obj.IsDescendant(PCursor::Class()), PInvalidCast);
  282.   return hCursor == ((const PCursor &)obj).hCursor ? EqualTo : GreaterThan;
  283. }
  284. static char * GetMaskBits(const PPixelImage & mask)
  285. {
  286.   HBITMAP hMask = mask->GetHBITMAP(NULL);
  287.   BITMAP bm;
  288.   GetObject(hMask, sizeof(bm), (LPSTR)&bm);
  289.   int bufSize = bm.bmHeight*bm.bmWidthBytes;
  290.   char * bits = new char[bufSize];
  291.   GetBitmapBits(hMask, bufSize, bits);
  292.   DeleteObject(hMask);
  293.   return bits;
  294. }
  295. PCursor::PCursor(const PPixelImage & andMask,
  296.                           const PPixelImage & xorMask, const PPoint & hotSpot)
  297. {
  298.   PApplication & owner = PApplication::Current();
  299.   PAssert(andMask->GetDepth() == 1 &&
  300.           andMask->GetDimensions() == owner.GetCursorSize() &&
  301.           xorMask->GetDepth() == 1 &&
  302.           xorMask->GetDimensions() == owner.GetCursorSize(),
  303.                                             "Incompatible images for cursor");
  304.   PAssert((PDIMENSION)hotSpot.X() < andMask->Width() &&
  305.           (PDIMENSION)hotSpot.Y() < andMask->Height(),
  306.           "Bad hot spot for cursor");
  307.   char * andMaskBits = GetMaskBits(andMask);
  308.   char * xorMaskBits = GetMaskBits(xorMask);
  309.   hCursor = CreateCursor(owner.GetInstance(),
  310.                          hotSpot.X(), hotSpot.Y(),
  311.                          andMask->Width(), andMask->Height(),
  312.                          andMaskBits, xorMaskBits);
  313.   delete [] andMaskBits;
  314.   delete [] xorMaskBits;
  315.   deleteCursor = TRUE;
  316.   PAssertOS(hCursor != NULL);
  317. }
  318. void PCursor::DestroyContents()
  319. {
  320.   if (deleteCursor && hCursor != NULL) {
  321.     PAssertOS(SetCursor(LoadCursor(NULL, IDC_ARROW)) != NULL);
  322.     PAssertOS(DestroyCursor(hCursor));
  323.     hCursor = NULL;
  324.   }
  325. }
  326. void PCursor::CopyContents(const PCursor & curs)
  327. {
  328.   hCursor = curs.hCursor;
  329.   deleteCursor = curs.deleteCursor;
  330. }
  331. //////////////////////////////////////////////////////////////////////////////
  332. // PCaret
  333. void PCaret::DestroyContents()
  334. {
  335.   Deactivate(activeWindow);
  336. }
  337. void PCaret::CopyContents(const PCaret & c)
  338. {
  339.   caretSize = c.caretSize;
  340.   activeWindow = c.activeWindow;
  341. }
  342. #if defined(_WIN32)
  343. #define PCaretAssertOS PAssertOS
  344. #else
  345. #define PCaretAssertOS
  346. #endif
  347. void PCaret::Activate(PInteractor * activator, BOOL display)
  348. {
  349.   Deactivate(activeWindow);
  350.   if (caretSize.Width() > 0 && caretSize.Height() > 0) {
  351.     activeWindow = activator;
  352.     PCaretAssertOS(CreateCaret(activator->GetHWND(),
  353.                                  NULL, caretSize.Width(), caretSize.Height()));
  354.     SetPosition(activator);
  355.     if (display)
  356.       Show(activator);
  357.   }
  358. }
  359. void PCaret::Deactivate(PInteractor * activator)
  360. {
  361.   if (activeWindow != NULL && activeWindow == activator) {
  362.     PCaretAssertOS(DestroyCaret());
  363.     activeWindow = NULL;
  364.   }
  365. }
  366. void PCaret::Show(PInteractor * activator)
  367. {
  368.   if (activeWindow != NULL && activeWindow == activator)
  369.     PCaretAssertOS(ShowCaret(activator->GetHWND()));
  370. }
  371. void PCaret::Hide(PInteractor * activator)
  372. {
  373.   if (activeWindow != NULL && activeWindow == activator)
  374.     PCaretAssertOS(HideCaret(activator->GetHWND()));
  375. }
  376. void PCaret::SetPosition(PInteractor * activator)
  377. {
  378.   if (activeWindow != NULL && activeWindow == activator) {
  379.     PPoint pos = activator->GetCaretPos(PInteractor::PixelCoords);
  380.     PCaretAssertOS(SetCaretPos(pos.X(), pos.Y()));
  381.   }
  382. }
  383. void PCaret::SetDimensions(PDIMENSION dx, PDIMENSION dy)
  384. {
  385.   caretSize.SetWidth(dx);
  386.   caretSize.SetHeight(dy);
  387.   if (activeWindow != NULL)
  388.     Activate(activeWindow, FALSE);
  389. }
  390. ///////////////////////////////////////////////////////////////////////////////
  391. // PImgIcon
  392. PImgIcon::PImgIcon(PRESOURCE_ID resID)
  393. {
  394.   hBitmap = LoadBitmap(PApplication::Current().GetInstance(), MAKEINTRESOURCE(resID));
  395.   PAssert(hBitmap != NULL, "Could not load resource.");
  396. }
  397. PImgIcon::PImgIcon(PCanvas & canvas, const PPixelImage & pix)
  398. {
  399.   hBitmap = pix->GetHBITMAP(canvas.GetHDC());
  400.   PAssertOS(hBitmap != NULL);
  401. }
  402. PObject::Comparison PImgIcon::Compare(const PObject & obj) const
  403. {
  404.   PAssert(obj.IsDescendant(PImgIcon::Class()), PInvalidCast);
  405.   return hBitmap == ((const PImgIcon &)obj).hBitmap ? EqualTo : GreaterThan;
  406. }
  407. void PImgIcon::DestroyContents()
  408. {
  409.   if (hBitmap != NULL) {
  410.     PAssertOS(DeleteObject(hBitmap));
  411.     hBitmap = NULL;
  412.   }
  413. }
  414. PDim PImgIcon::GetDimensions() const
  415. {
  416.   BITMAP bm;
  417.   GetObject(hBitmap, sizeof(bm), (LPSTR)&bm);
  418.   return PDim((PDIMENSION)bm.bmWidth, (PDIMENSION)bm.bmHeight);
  419. }
  420. ///////////////////////////////////////////////////////////////////////////////
  421. // PIcon
  422. PIcon::PIcon(PRESOURCE_ID resID)
  423.   : PImgIcon((HBITMAP)NULL)
  424. {
  425.   deleteIcon = FALSE;
  426.   switch ((unsigned)resID) {
  427.     case PSTD_ID_ICON_INFORMATION :
  428.       hIcon = LoadIcon(NULL, IDI_ASTERISK);
  429.       break;
  430.     case PSTD_ID_ICON_QUESTION :
  431.       hIcon = LoadIcon(NULL, IDI_QUESTION);
  432.       break;
  433.     case PSTD_ID_ICON_EXCLAMATION :
  434.       hIcon = LoadIcon(NULL, IDI_EXCLAMATION);
  435.       break;
  436.     case PSTD_ID_ICON_STOPSIGN :
  437.       hIcon = LoadIcon(NULL, IDI_HAND);
  438.       break;
  439.     case PSTD_ID_ICON_WINDOW :
  440.       hIcon = LoadIcon(NULL, IDI_APPLICATION);
  441.       break;
  442.     default :
  443.       hIcon = LoadIcon(PApplication::Current().GetInstance(), MAKEINTRESOURCE(resID));
  444.       deleteIcon = TRUE;
  445.   }
  446.   PAssertNULL(hIcon);
  447. }
  448. PObject::Comparison PIcon::Compare(const PObject & obj) const
  449. {
  450.   PAssert(obj.IsDescendant(PIcon::Class()), PInvalidCast);
  451.   return hIcon == ((const PIcon &)obj).hIcon ? EqualTo : GreaterThan;
  452. }
  453. void PIcon::DestroyContents()
  454. {
  455.   if (deleteIcon && hIcon != NULL) {
  456.     DestroyIcon(hIcon);
  457.     hIcon = NULL;
  458.   }
  459. }
  460. void PIcon::CopyContents(const PIcon & icon)
  461. {
  462.   deleteIcon = icon.deleteIcon;
  463.   hIcon = icon.hIcon;
  464. }
  465. PDim PIcon::GetDimensions() const
  466. {
  467.   return PDim((PDIMENSION)GetSystemMetrics(SM_CXICON),
  468.               (PDIMENSION)GetSystemMetrics(SM_CYICON));
  469. }
  470. ///////////////////////////////////////////////////////////////////////////////
  471. // PClipboard
  472. PClipboard::PClipboard(const PInteractor * wnd)
  473.   : owner(PAssertNULL(wnd))
  474. {
  475.   opened = OpenClipboard(wnd->GetHWND());
  476.   emptied = FALSE;
  477. }
  478. PClipboard::~PClipboard()
  479. {
  480.   if (opened)
  481.     PAssertOS(CloseClipboard());
  482. }
  483. BOOL PClipboard::HasFormat(Format fmt)
  484. {
  485.   static const UINT PClipboardFormats[NumFormats] = {
  486.     CF_TEXT, CF_BITMAP, CF_METAFILEPICT
  487.   };
  488.   
  489.   return opened && IsClipboardFormatAvailable(PClipboardFormats[fmt]);
  490. }
  491. BOOL PClipboard::HasFormat(const PString & fmt)
  492. {
  493.   return opened && IsClipboardFormatAvailable(RegisterClipboardFormat(fmt));
  494. }
  495. DWORD PClipboard::GetSize(const PString & fmt)
  496. {
  497.   if (!opened)
  498.     return 0;
  499.   HANDLE h = GetClipboardData(RegisterClipboardFormat(fmt));
  500.   return h != NULL ? GlobalSize(h) : 0;
  501. }
  502. BOOL PClipboard::GetData(const PString & fmt, void * data, DWORD max)
  503. {
  504.   if (!opened)
  505.     return FALSE;
  506.   HANDLE h = GetClipboardData(RegisterClipboardFormat(fmt));
  507.   if (h == NULL)
  508.     return FALSE;
  509.   DWORD size = GlobalSize(h);
  510.   memcpy(data, GlobalLock(h), (size_t)min(max, size));
  511.   GlobalUnlock(h);
  512.   return size <= max;
  513. }
  514.     
  515. BOOL PClipboard::SetData(const PString & fmt, const void * data, DWORD len)
  516. {
  517.   if (!opened)
  518.     return FALSE;
  519.   if (!emptied) {
  520.     EmptyClipboard();
  521.     emptied = TRUE;
  522.   }
  523.   
  524. #if !defined(_WIN32)
  525.   PAssert(len < 65536, PInvalidParameter);
  526. #endif
  527.   HANDLE h = GlobalAlloc(GHND, len);
  528.   memcpy(GlobalLock(h), data, (size_t)len);
  529.   GlobalUnlock(h);
  530.   return SetClipboardData(RegisterClipboardFormat(fmt), h) != NULL;
  531. }
  532. PString PClipboard::GetText()
  533. {
  534.   PString str;
  535.   HANDLE h = GetClipboardData(CF_TEXT);
  536.   if (h != NULL) {
  537.     DWORD size = GlobalSize(h);
  538. #if !defined(_WIN32)
  539.     PAssert(size < 65536, PInvalidParameter);
  540. #endif
  541.     lstrcpy(str.GetPointer((PINDEX)size), (LPSTR)GlobalLock(h));
  542.     GlobalUnlock(h);
  543.   }
  544.   return str;
  545. }
  546. BOOL PClipboard::SetText(const PString & str)
  547. {
  548.   if (!opened)
  549.     return FALSE;
  550.   if (!emptied) {
  551.     EmptyClipboard();
  552.     emptied = TRUE;
  553.   }
  554.   
  555.   PString winstr = PMakeOEMText(str);
  556.   HANDLE h = GlobalAlloc(GHND, winstr.GetLength()+1);
  557.   lstrcpy((LPSTR)GlobalLock(h), winstr);
  558.   GlobalUnlock(h);
  559.   SetClipboardData(CF_TEXT, h);
  560.   return TRUE;
  561. }
  562. PPixelImage PClipboard::GetPixels()
  563. {
  564.   HANDLE h = GetClipboardData(CF_BITMAP);
  565.   if (h != NULL)
  566.     return PPixelBase::CreateBitmap((HBITMAP)h);
  567.   return PPixelImage();
  568. }
  569. BOOL PClipboard::SetPixels(const PPixelImage & pix)
  570. {
  571.   if (!opened)
  572.     return FALSE;
  573.   if (!emptied) {
  574.     EmptyClipboard();
  575.     emptied = TRUE;
  576.   }
  577.   
  578.   PAssertOS(SetClipboardData(CF_BITMAP, pix->GetHBITMAP(NULL)) != NULL);
  579.   return TRUE;
  580. }
  581. PPictImage PClipboard::GetPict()
  582. {
  583.   PPictImage dwg;
  584. #if defined(_WIN32)
  585.   HENHMETAFILE h = (HENHMETAFILE)GetClipboardData(CF_ENHMETAFILE);
  586.   if (h != NULL)
  587.     dwg = PPictImage(new PPictBase(h));
  588. #else
  589.   HANDLE h = GetClipboardData(CF_METAFILEPICT);
  590.   if (h != NULL) {
  591.     LPMETAFILEPICT m = (LPMETAFILEPICT)GlobalLock(h);
  592.     dwg = PPictImage(new PPictBase(m->hMF));
  593.     GlobalUnlock(h);
  594.   }
  595. #endif
  596.   return dwg;
  597. }
  598. BOOL PClipboard::SetPict(const PPictImage & pic)
  599. {
  600.   if (!opened)
  601.     return FALSE;
  602.   if (!emptied) {
  603.     EmptyClipboard();
  604.     emptied = TRUE;
  605.   }
  606.   
  607. #if defined(_WIN32)
  608.   return SetClipboardData(CF_ENHMETAFILE, pic->GetMETAFILE()) != NULL;
  609. #else
  610.   HANDLE h = GlobalAlloc(GHND, sizeof(METAFILEPICT));
  611.   if (h == NULL)
  612.     return FALSE;
  613.   LPMETAFILEPICT m = (LPMETAFILEPICT)GlobalLock(h);
  614.   m->hMF = pic->GetMETAFILE();
  615.   GlobalUnlock(h);
  616.   SetClipboardData(CF_METAFILEPICT, h);
  617.   return TRUE;
  618. #endif
  619. }
  620. ///////////////////////////////////////////////////////////////////////////////
  621. // PApplication
  622. PApplication::PApplication(const char * manuf, const char * name,
  623.                            WORD major, WORD minor, CodeStatus stat, WORD build)
  624.   : PProcess(manuf, name, major, minor, stat, build),
  625.     systemFont("System", 12),
  626.     balloonFont("MS Sans Serif", 8)
  627. {
  628. }
  629. BOOL PApplication::IsGUIProcess() const
  630. {
  631.   return TRUE;
  632. }
  633. static PApplication * PApplicationInstance;
  634. LRESULT PEXPORTED WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
  635. {
  636.   return PApplicationInstance->WndProc(hWnd,msg,wParam,lParam);
  637. }
  638. BOOL PEXPORTED DlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
  639. {
  640.   return PApplicationInstance->DlgProc(hWnd,msg,wParam,lParam);
  641. }
  642. BOOL PEXPORTED FileDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
  643. {
  644.   return PApplicationInstance->FileDlgProc(hWnd,msg,wParam,lParam);
  645. }
  646. BOOL PEXPORTED PrintDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
  647. {
  648.   return PApplicationInstance->PrintDlgProc(hWnd, msg, wParam, lParam);
  649. }
  650. BOOL PEXPORTED FontDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
  651. {
  652.   return PApplicationInstance->FontDlgProc(hWnd,msg,wParam,lParam);
  653. }
  654. BOOL PEXPORTED ColourDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
  655. {
  656.   return PApplicationInstance->ColourDlgProc(hWnd, msg, wParam, lParam);
  657. }
  658. #define SET_DLG_PROC(proc) 
  659.                wndProcPtr[PApplication::proc##ProcType] = (WNDPROC)::proc##Proc
  660. int PApplication::_main(void * arg)
  661. {
  662.   PApplicationInstance = this;
  663.   hInstance = (HINSTANCE)arg;
  664.   SET_DLG_PROC(Wnd);
  665.   SET_DLG_PROC(Dlg);
  666.   SET_DLG_PROC(FileDlg);
  667.   SET_DLG_PROC(PrintDlg);
  668.   SET_DLG_PROC(FontDlg);
  669.   SET_DLG_PROC(ColourDlg);
  670.   Construct();
  671. #if PMEMORY_CHECK
  672.   PMemoryHeap::SetIgnoreAllocations(TRUE);
  673. #endif
  674.   ostream * debugStream = new PDebugStream;
  675.   PSetErrorStream(debugStream);  // Use OutputDebugString() stream
  676.   PTrace::SetStream(debugStream);
  677. #if PMEMORY_CHECK
  678.   PMemoryHeap::SetIgnoreAllocations(FALSE);
  679. #endif
  680.   blowUpTimeout = 1000;
  681.   doubleClick = 250;
  682.   mainWindow = NULL;
  683.   receivedQuitMessage = FALSE;
  684.   hAccelerator = NULL;
  685.   mdiClient = NULL;
  686.   defaultHelpFile = GetFile();
  687.   defaultHelpFile.SetType(".hlp");
  688.   HDC hDC = CreateCompatibleDC(NULL);
  689.   primaryScreenSize.SetWidth(GetSystemMetrics(SM_CXSCREEN));
  690.   primaryScreenSize.SetHeight(GetSystemMetrics(SM_CYSCREEN));
  691.   screenRect.SetX(GetSystemMetrics(SM_XVIRTUALSCREEN));
  692.   screenRect.SetY(GetSystemMetrics(SM_YVIRTUALSCREEN));
  693.   screenRect.SetWidth(GetSystemMetrics(SM_CXVIRTUALSCREEN));
  694.   screenRect.SetHeight(GetSystemMetrics(SM_CYVIRTUALSCREEN));
  695.   if (screenRect.Width() == 0 || screenRect.Height() == 0)
  696.     screenRect = primaryScreenSize;
  697.   screenResImperial.SetWidth((PDIMENSION)GetDeviceCaps(hDC, LOGPIXELSX));
  698.   screenResImperial.SetHeight((PDIMENSION)GetDeviceCaps(hDC, LOGPIXELSY));
  699.   screenResMetric.SetWidth((PDIMENSION)(screenResImperial.Width()*394L/1000L));
  700.   screenResMetric.SetHeight((PDIMENSION)(screenResImperial.Height()*394L/1000L));
  701.   cursorSize.SetWidth((PDIMENSION)GetSystemMetrics(SM_CXCURSOR));
  702.   cursorSize.SetHeight((PDIMENSION)GetSystemMetrics(SM_CYCURSOR));
  703.   iconSize.SetWidth((PDIMENSION)GetSystemMetrics(SM_CXICON));
  704.   iconSize.SetHeight((PDIMENSION)GetSystemMetrics(SM_CYICON));
  705.   titledBorder.SetWidth((PDIMENSION)GetSystemMetrics(SM_CXFRAME));
  706.   titledBorder.SetHeight((PDIMENSION)GetSystemMetrics(SM_CYFRAME));
  707.   dlgBorder.SetWidth((PDIMENSION)GetSystemMetrics(SM_CXDLGFRAME));
  708.   dlgBorder.SetHeight((PDIMENSION)GetSystemMetrics(SM_CYDLGFRAME));
  709.   border.SetWidth((PDIMENSION)GetSystemMetrics(SM_CXBORDER));
  710.   border.SetHeight((PDIMENSION)GetSystemMetrics(SM_CYBORDER));
  711.   defMainWindow.SetWidth((PDIMENSION)CW_USEDEFAULT);
  712.   defMainWindow.SetHeight((PDIMENSION)CW_USEDEFAULT);
  713.   defTitledWindow.SetWidth((PDIMENSION)CW_USEDEFAULT);
  714.   defTitledWindow.SetHeight((PDIMENSION)CW_USEDEFAULT);
  715.   screenColours = GetDeviceCaps(hDC, NUMCOLORS);
  716.   screenDepth = (PDIMENSION)(GetDeviceCaps(hDC, BITSPIXEL)*GetDeviceCaps(hDC, PLANES));
  717.   heightTitle = (PDIMENSION)GetSystemMetrics(SM_CYCAPTION);
  718.   heightMenu = (PDIMENSION)GetSystemMetrics(SM_CYMENU);
  719.   heightHScroll = (PDIMENSION)GetSystemMetrics(SM_CYHSCROLL);
  720.   widthVScroll = (PDIMENSION)GetSystemMetrics(SM_CXVSCROLL);
  721.   dblClkRect.SetWidth((PDIMENSION)GetSystemMetrics(SM_CXDOUBLECLK));
  722.   dblClkRect.SetHeight((PDIMENSION)GetSystemMetrics(SM_CYDOUBLECLK));
  723.   dblClkRect.Offset(-GetSystemMetrics(SM_CXDOUBLECLK)/2,
  724.                     -GetSystemMetrics(SM_CYDOUBLECLK)/2);
  725.   windowFg.FromSYSCOLOR(COLOR_WINDOWTEXT);
  726.   windowBk.FromSYSCOLOR(COLOR_WINDOW);
  727.   highlightFg.FromSYSCOLOR(COLOR_HIGHLIGHTTEXT);
  728.   highlightBk.FromSYSCOLOR(COLOR_HIGHLIGHT);
  729.   menuFg.FromSYSCOLOR(COLOR_MENUTEXT);
  730.   menuBk.FromSYSCOLOR(COLOR_MENU);
  731.   balloonFg = menuFg;
  732.   balloonBk = menuBk;
  733.   grayText.FromSYSCOLOR(COLOR_GRAYTEXT);
  734.   buttonFg.FromSYSCOLOR(COLOR_BTNTEXT);
  735.   buttonBk.FromSYSCOLOR(COLOR_BTNFACE);
  736.   buttonLighting.FromSYSCOLOR(COLOR_BTNHIGHLIGHT);
  737.   buttonShadow.FromSYSCOLOR(COLOR_BTNSHADOW);
  738.   scrollBar.FromSYSCOLOR(COLOR_SCROLLBAR);
  739.   activeTitleFg.FromSYSCOLOR(COLOR_CAPTIONTEXT);
  740.   activeTitleBk.FromSYSCOLOR(COLOR_ACTIVECAPTION);
  741.   inactiveTitleFg.FromSYSCOLOR(COLOR_INACTIVECAPTIONTEXT);
  742.   inactiveTitleBk.FromSYSCOLOR(COLOR_INACTIVECAPTION);
  743.   activeBorder.FromSYSCOLOR(COLOR_ACTIVEBORDER);
  744.   inactiveBorder.FromSYSCOLOR(COLOR_INACTIVEBORDER);
  745.   DeleteDC(hDC);
  746.   systemFont = PRealFont((HFONT)GetStockObject(DEFAULT_GUI_FONT));
  747.   createdWindows.DisallowDeleteObjects();
  748.   nonModalDialogs.DisallowDeleteObjects();
  749.   delayedCreateInteractors.DisallowDeleteObjects();
  750. #ifndef P_PLATFORM_HAS_THREADS
  751.   timerWnd = CreateWindow("STATIC", "",
  752.                             WS_POPUP, 0, 0, 0, 0, NULL, NULL, hInstance, NULL);
  753.   SetWindowLong(PAssertNULL(timerWnd),
  754.                                   GWL_WNDPROC, (DWORD)wndProcPtr[WndProcType]);
  755.   lastSetTimerTick = 1; // Needs to be non-zero
  756. #endif
  757.   Main();
  758.   return GetTerminationValue();
  759. }
  760. void PApplication::Main()
  761. {
  762.   while (ProcessMessage()) {
  763.     windowsMutex.Wait();
  764.     if (!delayedCreateInteractors.IsEmpty()) {
  765.       for (PINDEX i = 0; i < delayedCreateInteractors.GetSize(); i++)
  766.         delayedCreateInteractors[i].CreateHWND();
  767.       delayedCreateInteractors.RemoveAll();
  768.       delayedCreateInteractorsDone.Signal();
  769.     }
  770.     windowsMutex.Signal();
  771.     delayedCloseInteractors.RemoveAll();
  772.   }
  773. }
  774.   
  775. #ifndef P_PLATFORM_HAS_THREADS
  776. void PApplication::OperatingSystemYield()
  777. {
  778.   // Assure other MS-Windows tasks gets some time as well
  779.   MSG msg;
  780.   UINT id = 0x7fff;
  781.   while (PeekMessage(&msg, NULL, id, id, PM_NOREMOVE))
  782.     id--;
  783.   GetTimerList()->Process();
  784. }
  785. #endif
  786. BOOL PApplication::ProcessMessage()
  787. {
  788.   if (receivedQuitMessage)
  789.     return FALSE;
  790.   MSG msg;
  791.   receivedQuitMessage = GetMessage(&msg, NULL, 0, 0) == 0;
  792.   if (receivedQuitMessage)
  793.     return FALSE;
  794.   windowsMutex.Wait();
  795.   for (PINDEX i = 0; i < nonModalDialogs.GetSize(); i++) {
  796.     if (IsDialogMessage(nonModalDialogs[i].GetHWND(), &msg)) {
  797.       windowsMutex.Signal();
  798.       PassMainLoop();
  799.       return TRUE;
  800.     }
  801.   }
  802.   windowsMutex.Signal();
  803.   if (mdiClient != NULL && TranslateMDISysAccel(mdiClient, &msg)) {
  804.     PassMainLoop();
  805.     return TRUE;
  806.   }
  807.   if (hAccelerator != NULL &&
  808.              TranslateAccelerator(mainWindow->GetHWND(), hAccelerator, &msg)) {
  809.     PassMainLoop();
  810.     return TRUE;
  811.   }
  812.   TranslateMessage(&msg);
  813.   DispatchMessage(&msg);
  814.   PassMainLoop();
  815.   return TRUE;
  816. }
  817. LRESULT PApplication::WndProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)
  818. {
  819.   LRESULT retval;
  820. #ifndef P_PLATFORM_HAS_THREADS
  821.   if (hWnd == timerWnd)
  822.     retval = DefWindowProc(hWnd, msg, wParam, lParam);
  823.   else {
  824. #endif
  825.     PInteractor * window = (PInteractor *)createdWindows.GetAt(HWNDKey(hWnd));
  826.     if (window == NULL)
  827.       retval = DefWindowProc(hWnd, msg, wParam, lParam);
  828.     else {
  829.       PInteractor::_WindowsMessage message;
  830.       message.event = msg;
  831.       message.wParam = wParam;
  832.       message.lParam = lParam;
  833.       message.lResult = 0;
  834.       message.processed = TRUE;
  835.       PInteractor::_WindowsMessage * oldMessage = window->_msg;
  836.       window->_msg = &message;
  837.       window->WndProc();
  838.       window->_msg = oldMessage;
  839.       retval = message.lResult;
  840.     }
  841. #ifndef P_PLATFORM_HAS_THREADS
  842.   }
  843.   if (timerWnd != NULL &&
  844.           lastSetTimerTick != 0 && lastSetTimerTick != (UINT)GetTickCount()) {
  845.     lastSetTimerTick = 0; // Prevent recursive calls
  846.     Yield(); // Do the multithreading
  847.     long delay = GetTimerList()->Process().GetInterval();
  848.     if (!IsOnlyThread())
  849.       delay = PTimer::Resolution();
  850.     else if (delay > 60000)
  851.       delay = 60000;
  852.     KillTimer(timerWnd, 1);
  853.     PAssertOS(SetTimer(timerWnd, 1, (UINT)delay, NULL) != 0);
  854.     // Not too often or it gets really slow
  855.     lastSetTimerTick = (UINT)GetTickCount();
  856.     if (lastSetTimerTick == 0)
  857.       lastSetTimerTick++;
  858.   }
  859. #endif
  860.   return retval;
  861. }
  862. void PApplication::AddDialog(PInteractorLayout * pWnd)
  863. {
  864.   windowsMutex.Wait();
  865.   nonModalDialogs.Append(pWnd);
  866.   windowsMutex.Signal();
  867. }
  868. void PApplication::RemoveDialog(PInteractorLayout * pWnd)
  869. {
  870.   windowsMutex.Wait();
  871.   if (nonModalDialogs.GetObjectsIndex(pWnd) != P_MAX_INDEX)
  872.     nonModalDialogs.Remove(pWnd);
  873.   windowsMutex.Signal();
  874. }
  875. static void DoHelp(PTopLevelWindow * wnd,
  876.                    const PFilePath & helpFile,
  877.                    UINT fuCmd, DWORD dwData)
  878. {
  879.   PFilePath realHelpFile = helpFile;
  880.   if (realHelpFile.GetType().IsEmpty())
  881.     realHelpFile.SetType(".hlp");
  882.   WinHelp(wnd->GetHWND(), realHelpFile, fuCmd, dwData);
  883. }
  884. void PApplication::Terminate()
  885. {
  886. #ifndef P_PLATFORM_HAS_THREADS
  887.   KillTimer(timerWnd, 1);
  888.   lastSetTimerTick = 0; // Prevent WndProc from doing anything with timers
  889. #endif
  890.   if (mainWindow != NULL) {
  891.     DoHelp(mainWindow, defaultHelpFile, HELP_QUIT, 0);
  892.     DelayedCloseInteractor(mainWindow);
  893.     mainWindow = NULL;
  894.   }
  895.   PostQuitMessage(0);
  896. }
  897. void PApplication::DoContextHelp(const PString & context,
  898.                                                         const PFilePath & file)
  899. {
  900.   DoHelp(mainWindow, file, HELP_KEY, (DWORD)(const char *)context);
  901. }
  902. void PApplication::DoContextHelp(PINDEX context, const PFilePath & file)
  903. {
  904.   switch ((unsigned)context) {
  905.     case PSTD_ID_HELP_CONTENTS :
  906.       DoHelp(mainWindow, file, HELP_CONTENTS, 0);
  907.       break;
  908.     case PSTD_ID_HELP_SEARCH :
  909.       DoHelp(mainWindow, file, HELP_PARTIALKEY, (DWORD)"");
  910.       break;
  911.     case PSTD_ID_HELP_ON_HELP :
  912.       DoHelp(mainWindow, file, HELP_HELPONHELP, 0);
  913.       break;
  914.     default :
  915.       DoHelp(mainWindow, file, HELP_KEY, context);
  916.   }
  917. }
  918. PString PMakeOEMText(const PString & txt)
  919. {
  920.   PString s;
  921.   PINDEX lastPos = 0;
  922.   PINDEX searchPos = 0;
  923.   PINDEX pos;
  924.   while ((pos = txt.FindOneOf("rn", searchPos)) != P_MAX_INDEX) {
  925.     if (txt[pos] == 'r' && txt[pos+1] == 'n')
  926.       searchPos = pos + 2;
  927.     else {
  928.       if (pos > 0)
  929.         s += txt(lastPos, pos-1);
  930.       s += "rn";
  931.       lastPos = pos + 1;
  932.       searchPos = lastPos;
  933.     }
  934.   }
  935.   return s + txt(lastPos, pos);
  936. }
  937. // End Of File ///////////////////////////////////////////////////////////////