📄 misc.cxx
字号:
/*
* misc.cxx
*
* Miscellaneous GUI class 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: misc.cxx,v $
* Revision 1.67 2000/08/31 02:54:10 robertj
* Fixed problem with closing GUI app from non-process thread.
*
* Revision 1.66 2000/03/17 20:32:22 robertj
* Fixed race conditions in mult-threaded windows (dialogs in particular)
*
* Revision 1.65 2000/03/04 07:50:05 robertj
* Fixed problem with window not appearing when assert on GUI based win32 apps.
*
* Revision 1.64 1999/11/06 05:13:47 robertj
* Fixed reporting of memory leak that isn't for debug/trace stream.
*
* Revision 1.63 1999/10/24 11:52:05 robertj
* Fixed problems with creating/deleting dialogs from background threads.
*
* Revision 1.62 1999/08/17 03:46:42 robertj
* Fixed usage of inlines in optimised version.
*
* Revision 1.61 1999/08/07 07:13:23 robertj
* Fixed problems with "balloon help" text popup.
*
* Revision 1.60 1999/06/14 07:59:39 robertj
* Enhanced tracing again to add options to trace output (timestamps etc).
*
* Revision 1.59 1999/02/22 10:11:06 robertj
* Added trace stream output to debug output stream.
*
* Revision 1.58 1998/12/12 00:45:44 robertj
* new directory structure
*
* Revision 1.57 1998/11/30 04:49:50 robertj
* New directory structure
*
* Revision 1.56 1998/10/13 14:14:41 robertj
* Complete rewrite of memory leak detection code.
*
* Revision 1.55 1998/09/24 03:42:53 robertj
* Added open software license.
*
* Revision 1.54 1998/04/07 13:31:34 robertj
* Changed startup code to support PApplication class.
*
* Revision 1.53 1998/03/09 01:34:53 robertj
* Changed "system" font to not be the system font, WIn95 weirdness.
*
* Revision 1.52 1997/07/08 12:56:31 robertj
* DLL support
*
* Revision 1.51 1997/04/27 05:50:34 robertj
* DLL support.
*
* Revision 1.50 1996/10/31 12:39:57 robertj
* Added RCS keywords.
*
*/
#include <pwlib.h>
#include <ptlib\debstrm.h>
#if !P_USE_INLINES
#include <pwlib\pwlib.inl>
#endif
#define new PNEW
//
// If we are building with Win95/NT4 headers, we need to declare
// the multimonitor-related metrics ourselves.
//
#ifndef SM_CMONITORS
#define SM_XVIRTUALSCREEN 76
#define SM_YVIRTUALSCREEN 77
#define SM_CXVIRTUALSCREEN 78
#define SM_CYVIRTUALSCREEN 79
#define SM_CMONITORS 80
#define SM_SAMEDISPLAYFORMAT 81
#endif
///////////////////////////////////////////////////////////////////////////////
// PKeyCode
PKeyCode::PKeyCode(BOOL mouseMessage, WPARAM wParam, int other)
{
if (mouseMessage) {
value = (Value)other;
modifiers = NoModifier;
if ((wParam&MK_CONTROL) != 0)
modifiers = (Modifiers)(modifiers|Control);
if ((wParam&MK_SHIFT) != 0)
modifiers = (Modifiers)(modifiers|Shift);
if ((wParam&MK_LBUTTON) != 0)
modifiers = (Modifiers)(modifiers|LeftMouseButton);
if ((wParam&MK_RBUTTON) != 0)
modifiers = (Modifiers)(modifiers|RightMouseButton);
}
else {
static Value fromVK[] = {
NullValue, LeftButton, RightButton, Cancel, MiddleButton, NullValue,
NullValue, NullValue, BackSpace, Tab, NullValue, NullValue, Clear,
Return, NullValue, NullValue, ShiftKey, ControlKey, Altkey, Oem1,
CapsLockKey, NullValue, NullValue, NullValue, NullValue, NullValue,
NullValue, Escape, NullValue, NullValue, NullValue, NullValue, Space,
PageUp, PageDown, End, Home, Left, Up, Right, Down, Oem2, Oem3,
Oem4, Oem5, Insert, Delete, Help, KB0, KB1, KB2, KB3, KB4,
KB5, KB6, KB7, KB8, KB9, NullValue, NullValue, NullValue, NullValue,
NullValue, NullValue, NullValue, A, B, C, D, E, F, G, H, I, J, K, L, M,
N, O, P, Q, R, S, T, U, V, W, X, Y, Z, NullValue, NullValue, NullValue,
NullValue, NullValue, KP0, KP1, KP2, KP3, KP4, KP5, KP6, KP7, KP8, KP9,
Multiply, Add, Separator, Subtract, Decimal, Divide, F1, F2, F3, F4,
F5, F6, F7, F8, F9, F10, F11, F12, F13, F14, F15, F16, F17, F18, F19,
F20, F21, F22, F23, F24, NullValue, NullValue, NullValue, NullValue,
NullValue, NullValue, NullValue, NullValue, Oem6, Oem7,
NullValue, NullValue, NullValue, NullValue, NullValue, NullValue, //97
NullValue, NullValue, NullValue, NullValue, NullValue, NullValue, //9E
NullValue, NullValue, NullValue, NullValue, NullValue, NullValue, //A5
NullValue, NullValue, NullValue, NullValue, NullValue, NullValue, //AB
NullValue, NullValue, NullValue, NullValue, NullValue, NullValue, //B1
NullValue, NullValue, NullValue, NullValue, NullValue, NullValue, //B8
NullValue, Oem8, Oem10, Oem11, Oem12, Oem13, Oem14, Oem15,
NullValue, NullValue, NullValue, NullValue, NullValue, NullValue, //C6
NullValue, NullValue, NullValue, NullValue, NullValue, NullValue, //CC
NullValue, NullValue, NullValue, NullValue, NullValue, NullValue, //D2
NullValue, NullValue, NullValue, NullValue, NullValue, NullValue, //D8
NullValue, NullValue, Oem16, Oem17, Oem18, Oem19, Oem20, Oem21, //E0
Oem22, Oem23, Oem24, Oem25, NullValue, Oem26, NullValue, //E7
NullValue, Oem27, Oem28, Oem29, Oem30, Oem31, Oem32, Oem33, Oem34, //F0
Oem35, Oem36, Oem37, Oem38, Oem39
};
value = wParam < PARRAYSIZE(fromVK) ? fromVK[wParam] : NullValue;
modifiers = NoModifier;
}
}
WORD PKeyCode::VKCode()
{
static WORD toVK[LastCode] = {
0, VK_LBUTTON, VK_RBUTTON, VK_MBUTTON,
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
VK_NUMPAD0, VK_NUMPAD1, VK_NUMPAD2, VK_NUMPAD3, VK_NUMPAD4,
VK_NUMPAD5, VK_NUMPAD6, VK_NUMPAD7, VK_NUMPAD8, VK_NUMPAD9,
VK_ADD, VK_SUBTRACT, VK_MULTIPLY, VK_DIVIDE, VK_SEPARATOR, VK_DECIMAL,
VK_F1, VK_F2, VK_F3, VK_F4, VK_F5, VK_F6, VK_F7, VK_F8,
VK_F9, VK_F10, VK_F11, VK_F12, VK_F13, VK_F14, VK_F15, VK_F16,
VK_F17, VK_F18, VK_F19, VK_F20, VK_F21, VK_F22, VK_F23, VK_F24,
VK_UP, VK_DOWN, VK_LEFT, VK_RIGHT, VK_PRIOR, VK_NEXT, VK_HOME, VK_END,
VK_INSERT, VK_DELETE, VK_F20, VK_F21, VK_F22, VK_F23,
VK_CLEAR, VK_CANCEL, VK_HELP, VK_F24,
VK_BACK, VK_TAB, VK_RETURN, VK_ESCAPE, VK_SPACE,
VK_CAPITAL, VK_SHIFT, VK_CONTROL, VK_MENU, VK_CONTROL, VK_MENU, VK_MENU,
VK_PAUSE, VK_SELECT, 0x2a, VK_EXECUTE, VK_SNAPSHOT, VK_NUMLOCK, VK_SCROLL,
0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe6, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee,
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5
};
PAssert(value < LastCode, "Bad key code");
return toVK[value];
}
WORD PKeyCode::MouseModifiers()
{
WORD mm = 0;
if (IsModifier(Control))
mm |= MK_CONTROL;
if (IsModifier(Shift))
mm |= MK_SHIFT;
if (IsModifier(LeftMouseButton))
mm |= MK_LBUTTON;
if (IsModifier(RightMouseButton))
mm |= MK_RBUTTON;
return mm;
}
///////////////////////////////////////////////////////////////////////////////
// PResourceData
PResourceData::PResourceData(const PString & resType, PRESOURCE_ID resID)
{
HINSTANCE hInst = PApplication::Current().GetInstance();
HRSRC hRes = FindResource(hInst, MAKEINTRESOURCE(resID), resType);
hResource = LoadResource(hInst, PAssertNULL(hRes));
lpResource = (LPSTR)LockResource(PAssertNULL(hResource));
reference->size = 0; //(PINDEX)GlobalSize(hResource);
}
void PResourceData::CopyContents(const PResourceData & res)
{
hResource = res.hResource;
lpResource = res.lpResource;
}
PObject::Comparison PResourceData::Compare(const PObject & obj) const
{
PAssert(obj.IsDescendant(PResourceData::Class()), PInvalidCast);
return hResource == ((const PResourceData &)obj).hResource
? EqualTo : GreaterThan;
}
BOOL PResourceData::SetSize(PINDEX)
{
return TRUE;
}
void PResourceData::DestroyContents()
{
if (hResource != NULL) {
UnlockResource(hResource);
FreeResource(hResource);
hResource = NULL;
}
}
///////////////////////////////////////////////////////////////////////////////
// PResourceString
void PResourceString::Construct(PRESOURCE_ID resID)
{
PINDEX sz = 100;
do {
sz *= 2;
} while (LoadString(PApplication::Current().GetInstance(),
resID, GetPointer(sz+1), sz) >= sz);
MakeMinimumSize();
}
///////////////////////////////////////////////////////////////////////////////
// PCursor
PCursor::PCursor(PRESOURCE_ID resID)
{
deleteCursor = FALSE;
switch ((unsigned)resID) {
case PSTD_ID_CURSOR_ARROW :
hCursor = LoadCursor(NULL, IDC_ARROW);
break;
case PSTD_ID_CURSOR_IBEAM :
hCursor = LoadCursor(NULL, IDC_IBEAM);
break;
case PSTD_ID_CURSOR_WAIT :
hCursor = LoadCursor(NULL, IDC_WAIT);
break;
case PSTD_ID_CURSOR_CROSS :
hCursor = LoadCursor(NULL, IDC_CROSS);
break;
case PSTD_ID_CURSOR_MOVELEFT :
case PSTD_ID_CURSOR_MOVERIGHT :
case PSTD_ID_CURSOR_LEFTRIGHT :
hCursor = LoadCursor(NULL, IDC_SIZEWE);
break;
case PSTD_ID_CURSOR_MOVETOP :
case PSTD_ID_CURSOR_MOVEBOTTOM :
case PSTD_ID_CURSOR_UPDOWN :
hCursor = LoadCursor(NULL, IDC_SIZENS);
break;
case PSTD_ID_CURSOR_MOVETOPRIGHT :
case PSTD_ID_CURSOR_MOVEBOTLEFT :
hCursor = LoadCursor(NULL, IDC_SIZENESW);
break;
case PSTD_ID_CURSOR_MOVETOPLEFT :
case PSTD_ID_CURSOR_MOVEBOTRIGHT :
hCursor = LoadCursor(NULL, IDC_SIZENWSE);
break;
default :
hCursor = LoadCursor(PApplication::Current().GetInstance(),
MAKEINTRESOURCE(resID));
deleteCursor = TRUE;
}
PAssertOS(hCursor != NULL);
}
PObject::Comparison PCursor::Compare(const PObject & obj) const
{
PAssert(obj.IsDescendant(PCursor::Class()), PInvalidCast);
return hCursor == ((const PCursor &)obj).hCursor ? EqualTo : GreaterThan;
}
static char * GetMaskBits(const PPixelImage & mask)
{
HBITMAP hMask = mask->GetHBITMAP(NULL);
BITMAP bm;
GetObject(hMask, sizeof(bm), (LPSTR)&bm);
int bufSize = bm.bmHeight*bm.bmWidthBytes;
char * bits = new char[bufSize];
GetBitmapBits(hMask, bufSize, bits);
DeleteObject(hMask);
return bits;
}
PCursor::PCursor(const PPixelImage & andMask,
const PPixelImage & xorMask, const PPoint & hotSpot)
{
PApplication & owner = PApplication::Current();
PAssert(andMask->GetDepth() == 1 &&
andMask->GetDimensions() == owner.GetCursorSize() &&
xorMask->GetDepth() == 1 &&
xorMask->GetDimensions() == owner.GetCursorSize(),
"Incompatible images for cursor");
PAssert((PDIMENSION)hotSpot.X() < andMask->Width() &&
(PDIMENSION)hotSpot.Y() < andMask->Height(),
"Bad hot spot for cursor");
char * andMaskBits = GetMaskBits(andMask);
char * xorMaskBits = GetMaskBits(xorMask);
hCursor = CreateCursor(owner.GetInstance(),
hotSpot.X(), hotSpot.Y(),
andMask->Width(), andMask->Height(),
andMaskBits, xorMaskBits);
delete [] andMaskBits;
delete [] xorMaskBits;
deleteCursor = TRUE;
PAssertOS(hCursor != NULL);
}
void PCursor::DestroyContents()
{
if (deleteCursor && hCursor != NULL) {
PAssertOS(SetCursor(LoadCursor(NULL, IDC_ARROW)) != NULL);
PAssertOS(DestroyCursor(hCursor));
hCursor = NULL;
}
}
void PCursor::CopyContents(const PCursor & curs)
{
hCursor = curs.hCursor;
deleteCursor = curs.deleteCursor;
}
//////////////////////////////////////////////////////////////////////////////
// PCaret
void PCaret::DestroyContents()
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -