📄 cwindow.cpp
字号:
/*____________________________________________________________________________
Copyright (C) 2002 PGP Corporation
All rights reserved.
$Id: CWindow.cpp,v 1.6 2002/08/06 20:10:46 dallen Exp $
____________________________________________________________________________*/
#include "pgpClassesConfig.h"
#include "CString.h"
#include "UMath.h"
#include "CAccelerator.h"
#include "CDC.h"
#include "CRect.h"
#include "CSize.h"
#include "CWindow.h"
#include "UModuleInstance.h"
_USING_PGP
// Class CWindow static variables
PGPUInt32 CWindow::mWindowMapRefCount = 0;
CHashTable<CWindow> *CWindow::mWindowMap;
CRMWOLock *CWindow::mWindowMapLock;
// Class CWindow member functions
CWindow::CWindow() :
mWeCreated(FALSE), mWeSubclassed(FALSE),
mWeSubclassedUnicode(FALSE), mInModal(FALSE),
mSawClose(FALSE), mHwnd(NULL), mPrevWndProc(NULL)
{
}
CWindow::CWindow(HWND hWnd) :
mWeCreated(FALSE), mWeSubclassed(FALSE),
mWeSubclassedUnicode(FALSE), mInModal(FALSE),
mSawClose(FALSE), mHwnd(NULL), mPrevWndProc(NULL)
{
Attach(hWnd);
}
CWindow::~CWindow()
{
try
{
if (WeCreated())
Close();
else if (WeSubclassed())
UnSubclass();
}
catch (CComboError&) { }
}
CWindow&
CWindow::operator=(HWND hWnd)
{
Attach(hWnd);
return *this;
}
void
CWindow::Attach(HWND hWnd)
{
pgpAssert(!WeCreated());
pgpAssert(!WeSubclassed());
// Allow NULL hWnds.
if (IsntNull(hWnd))
{
pgpAssert(::IsWindow(hWnd));
}
mHwnd = hWnd;
}
void
CWindow::Center() const
{
// Center on parent, owner, or desktop window.
PGPBoolean isChild = (GetStyle() & WS_CHILD ? TRUE : FALSE);
HWND hwndCenter;
if (isChild)
hwndCenter = GetParent();
else
hwndCenter = GetWindow(GW_OWNER);
if (hwndCenter == NULL)
hwndCenter = GetDesktopWindow();
CWindow wndCenter(hwndCenter);
// Don't center on minimized or invisible windows.
PGPUInt32 wndCenterStyle = wndCenter.GetStyle();
if (!(wndCenterStyle & WS_VISIBLE) || (wndCenterStyle & WS_MINIMIZE))
return;
// Calculate coordinates.
CRect rcWindow;
GetWindowRect(rcWindow);
CRect rcCenter;
wndCenter.GetWindowRect(rcCenter);
CRect rcNew;
rcNew.Left() = (rcCenter.Left() + rcCenter.Right()) / 2 -
rcWindow.Width() / 2;
rcNew.Right() = rcNew.Left() + rcWindow.Width();
rcNew.Top() = (rcCenter.Top() + rcCenter.Bottom()) / 2 -
rcWindow.Height() / 2;
rcNew.Bottom() = rcNew.Top() + rcWindow.Height();
if (isChild)
wndCenter.ScreenToClient(rcNew);
// Move the window.
SetWindowPos(NULL, rcNew.Left(), rcNew.Top(), -1, -1,
SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
}
PGPBoolean
CWindow::ClientToScreen(CRect& rect)
{
CPoint point(rect.Left(), rect.Top());
CPoint translatedPoint = point;
PGPBoolean succeeded = ClientToScreen(translatedPoint);
if (succeeded)
{
rect.Offset(translatedPoint.X() - point.X(),
translatedPoint.Y() - point.Y());
}
return succeeded;
}
PGPBoolean
CWindow::FitFormattedTextToWindow(
const char *formatString,
const char *subString) const
{
// Get dimensions of window.
CRect windowRect;
GetWindowRect(windowRect);
PGPUInt32 xWindow = windowRect.Right() - windowRect.Left() - 3;
// Get dimensions of text without the substring.
CDC wndDC;
wndDC.AttachFromWindow(Handle());
CDC memDC;
memDC.CreateCompatible(wndDC);
HFONT oldFont = static_cast<HFONT>(memDC.SelectObject(
GetStockObject(DEFAULT_GUI_FONT)));
CString displayStr;
displayStr.Format(formatString, subString);
CSize messageSizeWSub = memDC.GetTextExtentPoint32(displayStr);
memDC.LPtoDP(messageSizeWSub);
PGPUInt32 widthMessageWSub = messageSizeWSub.CX();
// Will we have to truncate?
if (widthMessageWSub >= xWindow)
{
displayStr.Format(formatString, "");
CSize messageSizeWoSub = memDC.GetTextExtentPoint32(displayStr);
memDC.LPtoDP(messageSizeWoSub);
PGPUInt32 widthMessageWoSub = messageSizeWoSub.CX();
if (widthMessageWoSub < xWindow)
{
// We only have to truncate the substring.
CSize substringSize = memDC.GetTextExtentPoint32(subString);
memDC.LPtoDP(substringSize);
PGPUInt32 widthSubString = substringSize.CX();
PGPUInt32 xForSubstring = xWindow - widthMessageWoSub;
CString truncedSubStr(subString);
memDC.FitStringToWidth(truncedSubStr, xForSubstring);
displayStr.Format(formatString, truncedSubStr.Get());
}
else
{
// We must truncate both format and substring combined.
displayStr.Format(formatString, subString);
memDC.FitStringToWidth(displayStr, xWindow);
}
}
memDC.SelectObject(oldFont);
memDC.Clear();
wndDC.Clear();
// Display the text.
return SetWindowText(displayStr);
}
PGPBoolean
CWindow::FitTextToWindow(const char *cstr) const
{
// Get dimensions of window.
CRect windowRect;
GetWindowRect(windowRect);
// Get dimensions of text to be written
CDC wndDC;
wndDC.AttachFromWindow(Handle());
CDC memDC;
memDC.CreateCompatible(wndDC);
HFONT oldFont = static_cast<HFONT>(memDC.SelectObject(
GetStockObject(DEFAULT_GUI_FONT)));
PGPUInt32 xWindow = windowRect.Right() - windowRect.Left() - 3;
CString displayStr(cstr);
memDC.FitStringToWidth(displayStr, xWindow);
memDC.SelectObject(oldFont);
memDC.Clear();
wndDC.Clear();
// Display the text.
return SetWindowText(displayStr);
}
PGPBoolean
CWindow::GetClientRect(RECT& rect) const
{
return ::GetClientRect(Handle(), &rect);
}
PGPBoolean
CWindow::GetWindowRect(RECT& rect) const
{
return ::GetWindowRect(Handle(), &rect);
}
PGPBoolean
CWindow::GetWindowText(CString& text) const
{
PGPInt32 length = GetWindowTextLength(Handle());
return ::GetWindowText(Handle(), text.GetBuffer(length + 1), length + 1);
}
PGPInt32
CWindow::MapWindowPoints(
HWND hwndTo,
LPPOINT points,
PGPUInt32 numPoints) const
{
PGPInt32 result = ::MapWindowPoints(Handle(), hwndTo, points,
numPoints);
if (result == 0)
THROW_ERRORS(kPGPError_Win32WindowOpFailed, GetLastError());
return result;
}
PGPBoolean
CWindow::MoveWindow(
PGPInt32 X,
PGPInt32 Y,
PGPInt32 width,
PGPInt32 height,
PGPBoolean repaint) const
{
return ::MoveWindow(Handle(), X, Y, width, height, repaint);
}
PGPBoolean
CWindow::ScreenToClient(CRect& rect)
{
CPoint point(rect.Left(), rect.Top());
CPoint translatedPoint = point;
PGPBoolean succeeded = ScreenToClient(translatedPoint);
if (succeeded)
{
rect.Offset(translatedPoint.X() - point.X(),
translatedPoint.Y() - point.Y());
}
return succeeded;
}
PGPBoolean
CWindow::SetWindowText(const char *text) const
{
pgpAssertStrValid(text);
return (::SetWindowText(Handle(), text) == 0 ? FALSE : TRUE);
}
PGPBoolean
CWindow::SetWindowPos(
HWND hWndInsertAfter,
PGPInt32 X,
PGPInt32 Y,
PGPInt32 cx,
PGPInt32 cy,
PGPUInt32 uFlags) const
{
return (::SetWindowPos(Handle(), hWndInsertAfter, X, Y, cx, cy,
uFlags) ? TRUE : FALSE);
}
PGPBoolean
CWindow::GetClassInfo(const char *className, WNDCLASSEX& classEx)
{
pgpAssertStrValid(className);
classEx.cbSize = sizeof(classEx);
return GetClassInfoEx(UModuleInstance::Get(), className, &classEx);
}
ATOM
CWindow::RegisterClass(const char *className, WNDCLASSEX& classEx)
{
pgpAssertStrValid(className);
classEx.cbSize = sizeof(classEx);
classEx.lpfnWndProc = GlobalWindowProc;
classEx.hInstance = UModuleInstance::Get();
classEx.lpszClassName = className;
ATOM classAtom = RegisterClassEx(&classEx);
if (IsNull(classAtom))
THROW_ERRORS(kPGPError_Win32WindowOpFailed, GetLastError());
return classAtom;
}
ATOM
CWindow::RegisterClass(
const char *className,
PGPUInt32 style,
PGPInt32 clsExtra,
PGPInt32 wndExtra,
HICON icon,
HICON smallIcon,
HCURSOR cursor,
HBRUSH background,
const char *menuName)
{
pgpAssertStrValid(className);
WNDCLASSEX classEx;
classEx.style = style;
classEx.cbClsExtra = clsExtra;
classEx.cbWndExtra = wndExtra;
classEx.hIcon = icon;
classEx.hCursor = cursor;
classEx.hbrBackground = background;
classEx.lpszMenuName = menuName;
classEx.hIconSm = smallIcon;
ATOM classAtom = RegisterClass(className, classEx);
if (IsNull(classAtom))
THROW_ERRORS(kPGPError_Win32WindowOpFailed, GetLastError());
return classAtom;
}
void
CWindow::UnregisterClass(const char *classNameOrAtom)
{
pgpAssert(IsntNull(classNameOrAtom));
if (!::UnregisterClass(classNameOrAtom, UModuleInstance::Get()))
THROW_ERRORS(kPGPError_Win32WindowOpFailed, GetLastError());
}
void
CWindow::Subclass(HWND hWnd)
{
pgpAssert(!WeCreated());
pgpAssert(!WeSubclassed());
pgpAssert(::IsWindow(hWnd));
RefWindowMap();
try
{
Attach(hWnd);
mWeSubclassed = TRUE;
mWeSubclassedUnicode = FALSE;
mInModal = FALSE;
mSawClose = FALSE;
mPrevWndProc = reinterpret_cast<WNDPROC>(SetWindowLong(GWL_WNDPROC,
reinterpret_cast<LONG>(GlobalWindowProcSubclassed)));
if (IsNull(mPrevWndProc))
THROW_ERRORS(kPGPError_Win32WindowOpFailed, GetLastError());
AssocHandleToWindow(Handle(), this);
}
catch (CComboError&)
{
mWeSubclassed = FALSE;
DerefWindowMap();
throw;
}
}
void
CWindow::SubclassUnicode(HWND hWnd)
{
pgpAssert(!WeCreated());
pgpAssert(!WeSubclassed());
pgpAssert(::IsWindow(hWnd));
RefWindowMap();
try
{
Attach(hWnd);
mWeSubclassed = TRUE;
mWeSubclassedUnicode = TRUE;
mInModal = FALSE;
mSawClose = FALSE;
mPrevWndProc = reinterpret_cast<WNDPROC>(SetWindowLongW(
Handle(), GWL_WNDPROC,
reinterpret_cast<LONG>(GlobalWindowProcSubclassed)));
if (IsNull(mPrevWndProc))
THROW_ERRORS(kPGPError_Win32WindowOpFailed, GetLastError());
AssocHandleToWindow(Handle(), this);
}
catch (CComboError&)
{
mWeSubclassed = FALSE;
DerefWindowMap();
throw;
}
}
void
CWindow::UnSubclass()
{
pgpAssert(!WeCreated());
pgpAssert(WeSubclassed());
pgpAssert(IsntNull(mPrevWndProc));
if (mWeSubclassedUnicode)
SetWindowLongW(Handle(), GWL_WNDPROC, reinterpret_cast<LONG>(mPrevWndProc));
else
SetWindowLong(GWL_WNDPROC, reinterpret_cast<LONG>(mPrevWndProc));
if (IsNull(mPrevWndProc))
THROW_ERRORS(kPGPError_Win32WindowOpFailed, GetLastError());
mPrevWndProc = NULL;
mWeSubclassed = FALSE;
mHwnd = NULL;
DerefWindowMap();
}
void
CWindow::ShowModal(HACCEL accel)
{
pgpAssert(WeCreated());
mInModal = TRUE;
mSawClose = FALSE;
// Enter simple modal loop.
CWindow owner(GetWindow(GW_OWNER));
PGPBoolean shouldReEnable = FALSE;
if (owner.IsWindow() && (owner.Handle() != CWindow::GetDesktopWindow()))
shouldReEnable = !owner.EnableWindow(FALSE);
try
{
ShowWindow(SW_SHOW);
UpdateWindow();
CAccelerator caccel(accel);
while (TRUE)
{
CMessage msg;
if (msg.Get() < 1)
break;
if (IsntNull(accel))
{
if (!caccel.Translate(Handle(), msg))
{
msg.Translate();
msg.Dispatch();
}
}
else
{
msg.Translate();
msg.Dispatch();
}
if (mSawClose)
break;
}
if (shouldReEnable)
{
ShowWindow(SW_HIDE);
DestroyWindow();
owner.EnableWindow(TRUE);
owner.SetActiveWindow();
}
else
{
DestroyWindow();
}
}
catch (CComboError&)
{
if (shouldReEnable)
owner.EnableWindow(TRUE);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -