📄 dialogs.cxx
字号:
/*
* dialogs.cxx
*
* Dialog classes implementation.
*
* Portable Windows Library
*
* Copyright (c) 1993-1998 Equivalence Pty. Ltd.
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.0 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
* the License for the specific language governing rights and limitations
* under the License.
*
* The Original Code is Portable Windows Library.
*
* The Initial Developer of the Original Code is Equivalence Pty. Ltd.
*
* Portions are Copyright (C) 1993 Free Software Foundation, Inc.
* All Rights Reserved.
*
* Contributor(s): ______________________________________.
*
* $Log: dialogs.cxx,v $
* Revision 1.67 2000/09/27 01:31:52 robertj
* Fixed problem with no control value update if press "Enter" to close dialog.
*
* Revision 1.66 2000/04/04 22:26:20 robertj
* Fixed bug in PDialog when close button closes regardless of OnCancel() virtual.
*
* Revision 1.65 2000/03/17 20:32:22 robertj
* Fixed race conditions in mult-threaded windows (dialogs in particular)
*
* Revision 1.64 2000/03/04 13:08:35 robertj
* Moved common function in open file dialog to common source file.
*
* Revision 1.63 2000/03/04 10:09:38 robertj
* Fixed bugs in open file dialog (showed up in Win2K).
*
* Revision 1.62 1999/11/16 06:51:42 robertj
* Created PCustomListBox to allow motif native code PStringListBox implementation
*
* Revision 1.61 1999/11/01 00:07:44 robertj
* Changed semantics of OnClose() to be the same as PTitledWindow
*
* Revision 1.60 1999/10/24 11:52:05 robertj
* Fixed problems with creating/deleting dialogs from background threads.
*
* Revision 1.59 1999/08/25 05:13:33 robertj
* Fixed problem with calling modal dialog from a background thread.
*
* Revision 1.58 1999/08/07 07:13:23 robertj
* Fixed problems with "balloon help" text popup.
*
* Revision 1.57 1999/02/16 08:08:07 robertj
* MSVC 6.0 compatibility changes.
*
* Revision 1.56 1998/12/12 00:43:51 robertj
* Added functions for user request on printing selection only.
* Fixed transfer of start and end pages from PPrintDialog.
*
* Revision 1.55 1998/12/02 03:50:12 robertj
* Unix compatibility changes
*
* Revision 1.54 1998/09/24 03:42:39 robertj
* Added open software license.
*
* Revision 1.53 1998/09/24 01:55:32 robertj
* Fixed bug that caused modal dialog not to go away when closed from another thread.
*
* Revision 1.52 1998/09/22 15:09:45 robertj
* Fixed confusion in Font Dialog, variable at different levels with same name.
* Fixed Font Dialog not returning font that was selected.
*
* Revision 1.51 1998/09/17 04:25:56 robertj
* Fixed race condition if dialog is closed by a different thread to the PProcess thrad.
*
* Revision 1.50 1998/09/14 13:14:20 robertj
* Fixed memory leak on delete of PStringList, not deleting all its contents.
* Fixed failure to update control values on non-modal dialog box initialisation.
*
* Revision 1.49 1998/09/04 07:01:06 robertj
* Added a lot of DEVMODE infor for win95 to propagate from PrintDlg to PPrintCanvas.
*
* Revision 1.48 1998/03/20 03:12:44 robertj
* Fixed bug in standard file dialog getting filename and folder.
*
* Revision 1.47 1998/03/09 07:14:31 robertj
* Explorer based OpenDirDialog.
* More implementation of file type lists.
*
* Revision 1.46 1998/03/09 01:46:45 robertj
* Enhanced file types for standard file dialog.
*
* Revision 1.44 1996/11/04 03:32:25 robertj
* Fixed bug in background colour of dialogs.
*
* Revision 1.43 1996/10/31 12:39:56 robertj
* Added RCS keywords.
*
*/
#include <pwlib.h>
class PDummyListBox : public PListBox
{
PCLASSINFO(PDummyListBox, PListBox)
public:
PDummyListBox(PInteractorLayout * layout, PRESOURCE_ID ctrlID)
: PListBox(layout, ctrlID, PNotifier(), NULL) { }
virtual void OnDrawEntry(PINDEX, PObject &, PCanvas &, const PRect &, BOOL, BOOL)
{ }
virtual PDim OnMeasureEntry(PINDEX, PObject &, PCanvas &)
{ return PDim(); }
virtual BOOL IsOwnerDraw() const
{ return FALSE; }
};
#define new PNEW
///////////////////////////////////////////////////////////////////////////////
// PInteractorLayout
PInteractorLayout::PInteractorLayout(PInteractor * parent)
: PInteractor(parent)
{
focusInteractor = this;
pResourceID = (PRESOURCE_ID)-1;
}
PInteractorLayout::PInteractorLayout(PInteractor * parent, PRESOURCE_ID resID)
: PInteractor(parent)
{
focusInteractor = this;
pResourceID = resID;
}
PInteractorLayout::~PInteractorLayout()
{
if (_hWnd != NULL && PThread::Current() != owner) {
if (_hWnd != P_DEAD_WINDOW)
PostMessage(_hWnd, WM_CLOSE, 0, 0);
handledDestroySignal.Wait();
}
owner->RemoveDialog(this);
}
BOOL PEXPORTED EnumDlgChildren(HWND hWnd, PInteractorLayout * layout)
{
if (GetParent(hWnd) != layout->GetHWND())
return TRUE;
PRESOURCE_ID ctrlID = (PRESOURCE_ID)GetDlgCtrlID(hWnd);
if (ctrlID == 0xffff)
return TRUE;
if (layout->GetControl(ctrlID) != NULL)
return TRUE;
PControl * child = NULL;
char className[20];
GetClassName(hWnd, className, sizeof(className));
DWORD style = GetWindowLong(hWnd, GWL_STYLE);
if (lstrcmpi(className, "EDIT") == 0) {
if ((style&ES_MULTILINE) != 0)
child = new PMultiLineEditBox(layout, ctrlID, PNotifier(), NULL);
else {
char str[30];
GetWindowText(hWnd, str, sizeof(str));
SetWindowText(hWnd, "");
if (lstrcmpi(str, "INTEDIT") == 0)
child = new PIntegerEditBox(layout, ctrlID, PNotifier(), NULL);
else if (lstrcmpi(str, "REALEDIT") == 0)
child = new PFloatEditBox(layout, ctrlID, PNotifier(), NULL);
else
child = new PEditBox(layout, ctrlID, PNotifier(), NULL);
}
}
else if (lstrcmpi(className, "STATIC") == 0) {
switch (style&15) {
case SS_LEFT :
case SS_SIMPLE :
case SS_LEFTNOWORDWRAP :
case SS_CENTER :
case SS_RIGHT :
child = new PStaticText(layout, ctrlID, PNotifier(), NULL);
break;
case SS_ICON :
child = new PStaticIcon(layout, ctrlID, PNotifier(), NULL);
break;
}
}
else if (lstrcmpi(className, "BUTTON") == 0) {
switch (style&15) {
case BS_PUSHBUTTON :
case BS_DEFPUSHBUTTON :
child = new PTextButton(layout, ctrlID, PNotifier(), NULL);
break;
case BS_AUTOCHECKBOX :
case BS_CHECKBOX :
child = new PCheckBox(layout, ctrlID, PNotifier(), NULL);
break;
case BS_AUTO3STATE :
case BS_3STATE :
child = new PCheck3WayBox(layout, ctrlID, PNotifier(), NULL);
break;
case BS_AUTORADIOBUTTON :
case BS_RADIOBUTTON :
child = new PRadioButton(layout, ctrlID, PNotifier(), NULL);
break;
case BS_GROUPBOX :
child = new PStaticBox(layout, ctrlID, PNotifier(), NULL);
break;
}
}
else if (lstrcmpi(className, "LISTBOX") == 0) {
if ((style&LBS_OWNERDRAWVARIABLE) == 0)
child = new PDummyListBox(layout, ctrlID);
else
child = new PStringListBox(layout, ctrlID, PNotifier(), NULL);
}
else if (lstrcmpi(className, "COMBOBOX") == 0) {
switch (style&15) {
case CBS_DROPDOWN :
child = new PChoiceBox(layout, ctrlID, PNotifier(), NULL);
break;
case CBS_DROPDOWNLIST :
child = new PComboBox(layout, ctrlID, PNotifier(), NULL);
break;
}
}
else if (lstrcmpi(className, "SCROLLBAR") == 0) {
if ((style&1) != 0)
child = new PVerticalScrollBar(layout, ctrlID, PNotifier(), NULL);
else
child = new PHorizontalScrollBar(layout, ctrlID, PNotifier(), NULL);
}
return TRUE;
}
void PInteractorLayout::ConstructEnd(PRESOURCE_ID resID)
{
EnumChildWindows(GetHWND(), (WNDENUMPROC)EnumDlgChildren, (LPARAM)this);
PResourceData dialog("#5", resID);
PResourceData strings("DIALOGSTRINGS", resID);
#if defined(_WIN32)
PINDEX numControls = ((const DLGTEMPLATE *)(const BYTE *)dialog)->cdit;
const WORD * strptr = (const WORD *)(const BYTE *)strings;
const WORD * strbase;
#else
PINDEX numControls = dialog[4];
const char * strptr = (const char *)(const BYTE *)strings;
const char * strbase;
#endif
for (PINDEX i = 0; i < numControls; i++) {
PControl & child = (PControl &)children[i];
strbase = strptr;
PINDEX len = 0;
while (*strptr++ != 0)
len++;
if (len != 0)
child.SetBalloonHelp(PString(strbase, len));
while (*strptr != 0) {
strbase = strptr;
len = 0;
while (*strptr++ != 0)
len++;
if (child.IsDescendant(PChoiceBox::Class()))
((PChoiceBox&)child).AddString(PString(strbase, len));
else if (child.IsDescendant(PStringListBox::Class()))
((PStringListBox&)child).AddString(PString(strbase, len));
else if (child.IsDescendant(PComboBox::Class()))
((PComboBox&)child).AddString(PString(strbase, len));
}
strptr++;
}
for (i = 1; i < GetNumChildren(); i++) {
if (children[i].IsDescendant(PRadioButton::Class()) &&
children[i-1].IsDescendant(PRadioButton::Class()))
((PRadioButton &)children[i]).AddToGroup((PRadioButton &)children[i-1]);
}
UpdateControls();
}
void PInteractorLayout::GetCreateWinInfo(WNDCLASS & wndClass)
{
PInteractor::GetCreateWinInfo(wndClass);
wndClass.lpszClassName = "Dialog";
}
void PInteractorLayout::CreateHWND()
{
if (pResourceID != -1) {
_hWnd = CreateDialog(owner->GetInstance(),
MAKEINTRESOURCE(pResourceID),
parent->GetHWND(),
(DLGPROC)owner->GetWndProcPtr(PApplication::DlgProcType));
PAssert(_hWnd != NULL, PInvalidWindow);
PPoint pos = GetPosition(ScreenCoords);
if (pos.X() < 0 && pos.Y() < 0)
SetPosition(0,0,CentreParent,CentreParent);
HFONT hFont = (HFONT)(UINT)SendMessage(_hWnd, WM_GETFONT, 0, 0L);
if (hFont != NULL)
font = PRealFont(hFont);
else
SetFont(parent->GetFont(), TRUE);
}
else {
WNDCLASS dummyWndClass;
#if defined(_WIN32)
struct {
DLGTEMPLATE header;
WORD szMenuName[1], szClassName[1], szCaption[1];
WORD wPointSize;
WORD szFaceName[1];
} emptyDlg;
memset(&emptyDlg, 0, sizeof(emptyDlg));
GetCreateWinInfo(dummyWndClass);
emptyDlg.header.dwExtendedStyle = _exStyleBits;
#else
struct {
struct {
DWORD style;
BYTE bNumberOfItems;
WORD x, y, cx, cy;
} header;
char szMenuName[1], szClassName[1], szCaption[1];
WORD wPointSize;
char szFaceName[1];
} emptyDlg;
memset(&emptyDlg, 0, sizeof(emptyDlg));
GetCreateWinInfo(dummyWndClass);
#endif
emptyDlg.header.style = _styleBits;
_hWnd = CreateDialogIndirect(owner->GetInstance(),
&emptyDlg.header,
parent->GetHWND(),
(DLGPROC)owner->GetWndProcPtr(PApplication::DlgProcType));
PAssert(_hWnd != NULL, PInvalidWindow);
}
_styleBits = GetWindowLong(_hWnd, GWL_STYLE);
_exStyleBits = GetWindowLong(_hWnd, GWL_EXSTYLE);
owner->AddWindowHandle(_hWnd, this);
owner->AddDialog(this);
}
void PInteractorLayout::WndProc()
{
PInteractor::WndProc();
switch (_msg->event) {
case WM_CLOSE :
DestroyWindow(_hWnd);
break;
case WM_DESTROY :
owner->RemoveDialog(this);
handledDestroySignal.Signal();
break;
}
handledMessageSignal.Signal();
}
void PInteractorLayout::DefWndProc()
{
_msg->processed = FALSE;
}
///////////////////////////////////////////////////////////////////////////////
// PDialog
PDialog::PDialog(PInteractor * parent)
: PInteractorLayout(parent)
{
backgroundColour = owner->GetButtonBkColour();
}
PDialog::PDialog(PInteractor * parent, PRESOURCE_ID resID)
: PInteractorLayout(parent, resID)
{
backgroundColour = owner->GetButtonBkColour();
}
void PDialog::WndProc()
{
if (_msg->event == WM_CLOSE)
OnCancel();
else
PInteractor::WndProc();
}
void PDialog::GetCreateWinInfo(WNDCLASS & wndClass)
{
PInteractorLayout::GetCreateWinInfo(wndClass);
_styleBits = WS_POPUP|WS_CLIPCHILDREN|WS_CAPTION|WS_SYSMENU|WS_BORDER;
}
///////////////////////////////////////////////////////////////////////////////
// PFloatingDialog
void PFloatingDialog::Construct()
{
titleFont = PRealFont(PFont("MS Sans Serif", 1)); // Smallest font possible
borderWidth = owner->GetBorderSize().Width();
borderHeight = owner->GetBorderSize().Height();
titleHeight = titleFont.GetHeight(TRUE) + borderHeight*2;
}
void PFloatingDialog::WndProc()
{
switch (_msg->event) {
case WM_NCCALCSIZE :
NCCalcSize((LPNCCALCSIZE_PARAMS)_msg->lParam);
return;
case WM_NCHITTEST :
_msg->lResult = NCHitTest(_msg->lParam);
return;
case WM_NCPAINT :
NCPaint();
return;
}
PDialog::WndProc();
}
void PFloatingDialog::NCCalcSize(LPNCCALCSIZE_PARAMS cs)
{
PDim bdr = owner->GetBorderSize();
cs->rgrc[0].top += titleHeight + borderHeight;
cs->rgrc[0].left += borderWidth;
cs->rgrc[0].bottom -= borderHeight;
cs->rgrc[0].right -= borderWidth;
}
LRESULT PFloatingDialog::NCHitTest(const PPoint & pt)
{
PRect rect;
GetWindowRect(_hWnd, rect);
rect.Inflate(-(PORDINATE)borderWidth, -(PORDINATE)borderHeight);
if (!rect.ContainsPoint(pt))
return HTBORDER;
if (pt.Y() > rect.Y() + (PORDINATE)titleHeight)
return HTCLIENT;
if (pt.X() < rect.X() + (PORDINATE)titleHeight)
return HTSYSMENU;
return HTCAPTION;
}
void PFloatingDialog::NCPaint()
{
PDrawCanvas canvas(this, GetWindowDC(_hWnd), TRUE, TRUE);
PRect rect;
GetWindowRect(_hWnd, rect);
rect.SetOrigin(0, 0);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -