2025-11-27 16:46:48 +09:00

448 lines
13 KiB
C++

// ===================================================================================
// Class Implementation : COXSizeDialogBar
// ===================================================================================
// Header file : OXSizeDlgBar.cpp
// Version: 9.3
// This software along with its related components, documentation and files ("The Libraries")
// is © 1994-2007 The Code Project (1612916 Ontario Limited) and use of The Libraries is
// governed by a software license agreement ("Agreement"). Copies of the Agreement are
// available at The Code Project (www.codeproject.com), as part of the package you downloaded
// to obtain this file, or directly from our office. For a copy of the license governing
// this software, you may contact us at legalaffairs@codeproject.com, or by calling 416-849-8900.
// Some portions Copyright (C)1994-5 Micro Focus Inc, 2465 East Bayshore Rd, Palo Alto, CA 94303.
// //////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include <afxole.h>
#include <afxpriv.h>
#if _MFC_VER >= 0x0700
#include <afxocc.h>
#endif
#include "OXSizeDlgBar.h"
#include "UTB64Bit.h"
#ifdef _DEBUG
#undef THIS_FILE
static char BASED_CODE THIS_FILE[] = __FILE__;
#endif
IMPLEMENT_DYNAMIC(COXSizeDialogBar, COXSizeControlBar)
#define new DEBUG_NEW
GADGETRESIZEHANDLE CreateGadgetResizeHandle(CWnd* pWnd);
void DestroyGadgetResizeHandle(GADGETRESIZEHANDLE Handle);
void ResizeGadgetsOnWindow(GADGETRESIZEHANDLE Handle, int cx, int cy);
#ifndef _AFX_NO_OCC_SUPPORT
// Following header file is supplied as part of MFC4.0, but is NOT in the standard include directory.
// For convenience, a copy of occimpl.h is included along with these sources. If you upgrade MFc, you should
// ensure this source file is upgraded also.
#ifndef __OX_OCCIMPL_H__
#if _MFC_VER < 0x0700
#include <..\src\occimpl.h>
#else
// #include <..\src\mfc\occimpl.h>
#endif
#define __OX_OCCIMPL_H__
#endif
#endif
#ifndef __OXMFCIMPL_H__
#if _MFC_VER < 0x0700
#include <..\src\afximpl.h>
#else
#include <..\src\mfc\afximpl.h>
#endif
#define __OXMFCIMPL_H__
#endif
typedef struct _Rect_And_Hwnd
{
CRect m_rect;
HWND m_hWnd;
} RECT_AND_HWND;
struct COXSizeDialogBar_ExtData
{
_AFX_OCC_DIALOG_INFO* m_pOccDialogInfo;
LPCTSTR m_lpszTemplateName;
};
/////////////////////////////////////////////////////////////////////////////
// Definition of static members
// Data members -------------------------------------------------------------
// protected:
// private:
// Member functions ---------------------------------------------------------
// public:
#if defined(_AFXDLL) || (defined(_UNICODE) && _MFC_VER >= 0x0700)
#pragma message ( "oxsizedlgbar.cpp line 84 : VS 2003 may need this symbol defined" )
const TCHAR _afxWndControlBar[] = _T("AfxControlBar"); // class for control bars
#endif
COXSizeDialogBar::COXSizeDialogBar(int nStyle)
: COXSizeControlBar(nStyle)
{
m_GadgetResizeHandle = NULL;
#ifndef _AFX_NO_OCC_SUPPORT
m_lpszTemplateName = NULL;
m_pOccDialogInfo = NULL;
#endif
}
COXSizeDialogBar::~COXSizeDialogBar()
{
DestroyGadgetResizeHandle(m_GadgetResizeHandle);
DestroyWindow(); // avoid PostNcDestroy problems
}
BEGIN_MESSAGE_MAP(COXSizeDialogBar, COXSizeControlBar)
//{{AFX_MSG_MAP(COXSizeDialogBar)
ON_WM_ERASEBKGND()
//}}AFX_MSG_MAP
#ifndef _AFX_NO_OCC_SUPPORT
ON_MESSAGE(WM_INITDIALOG, HandleInitDialog)
#endif
END_MESSAGE_MAP()
#ifdef _DEBUG
/////////////////////////////////////////////////////////////////////////////
// Following is taken from afximpl.h, to check that the dialog template
// for a dialog bars are indeed ok to use. Only present if debugging
// Extended dialog templates (new in Win95)
#pragma pack(push, 1)
#pragma pack(pop)
// diagnostic routine to check for and decode dialog templates
// return FALSE if a program error occurs (i.e. bad resource ID or
// bad dialog styles).
BOOL AFXAPI CheckDialogTemplate(LPCTSTR lpszResource, BOOL bInvisibleChild)
{
ASSERT(lpszResource != NULL);
HINSTANCE hInst = AfxFindResourceHandle(lpszResource, RT_DIALOG);
HRSRC hResource = ::FindResource(hInst, lpszResource, RT_DIALOG);
if (hResource == NULL)
{
if (HIWORD(lpszResource) != 0)
TRACE1("ERROR: Cannot find dialog template named '%s'.\n",
lpszResource);
else
TRACE1("ERROR: Cannot find dialog template with IDD 0x%04X.\n",
LOWORD((DWORD_PTR)lpszResource));
return FALSE;
}
if (!bInvisibleChild)
return TRUE; // that's all we need to check
// we must check that the dialog template is for an invisible child
// window that can be used for a form-view or dialog-bar
HGLOBAL hTemplate = LoadResource(hInst, hResource);
if (hTemplate == NULL)
{
TRACE0("Warning: LoadResource failed for dialog template.\n");
// this is only a warning, the real call to CreateDialog will fail
return TRUE; // not a program error - just out of memory
}
DLGTEMPLATEEX* pTemplate = (DLGTEMPLATEEX*)LockResource(hTemplate);
DWORD dwStyle;
if (pTemplate->signature == 0xFFFF)
dwStyle = pTemplate->style;
else
dwStyle = ((DLGTEMPLATE*)pTemplate)->style;
UnlockResource(hTemplate);
FreeResource(hTemplate);
if (dwStyle & WS_VISIBLE)
{
if (HIWORD(lpszResource) != 0)
TRACE1("ERROR: Dialog named '%s' must be invisible.\n",
lpszResource);
else
TRACE1("ERROR: Dialog with IDD 0x%04X must be invisible.\n",
LOWORD((DWORD_PTR)lpszResource));
return FALSE;
}
if (!(dwStyle & WS_CHILD))
{
if (HIWORD(lpszResource) != 0)
TRACE1("ERROR: Dialog named '%s' must have the child style.\n",
lpszResource);
else
TRACE1("ERROR: Dialog with IDD 0x%04X must have the child style.\n",
LOWORD((DWORD_PTR)lpszResource));
return FALSE;
}
return TRUE;
}
#endif //_DEBUG
BOOL COXSizeDialogBar::Create(CWnd* pParentWnd, LPCTSTR lpszTemplateName,
UINT nStyle, UINT nID)
{
ASSERT(pParentWnd != NULL);
ASSERT(lpszTemplateName != NULL);
ASSERT((nStyle & WS_THICKFRAME)==NULL);
// Alas, MFC doesn't export many of the debugg-only functions, but I've added
// the code for this safety net as it helps track down errors faster, and
// only has an overhead in debug code
#ifdef _DEBUG
// dialog template must exist and be invisible with WS_CHILD set
if (!CheckDialogTemplate(lpszTemplateName, TRUE))
{
ASSERT(FALSE); // invalid dialog template name
PostNcDestroy(); // cleanup if Create fails too soon
return FALSE;
}
#endif //_DEBUG
// allow chance to modify styles
#if _MFC_VER <= 0x0421
m_dwStyle = nStyle;
#else
m_dwStyle = nStyle&CBRS_ALL;
#endif
CREATESTRUCT cs;
memset(&cs, 0, sizeof(cs));
cs.lpszClass = _afxWndControlBar;
cs.style = (DWORD)nStyle | WS_CHILD;
cs.hMenu = (HMENU)(UINT_PTR)nID;
cs.hInstance = AfxGetInstanceHandle();
cs.hwndParent = pParentWnd->GetSafeHwnd();
if (!PreCreateWindow(cs))
return FALSE;
// create a modeless dialog
#ifndef _AFX_NO_OCC_SUPPORT
m_lpszTemplateName = lpszTemplateName;
#endif
// initialize common controls
//VERIFY(AfxDeferRegisterClass(AFX_WNDCOMMCTLS_REG));
BOOL bSuccess = CreateDlg(lpszTemplateName, pParentWnd);
#ifndef _AFX_NO_OCC_SUPPORT
m_lpszTemplateName = NULL;
#endif
if (!bSuccess)
return FALSE;
// dialog template MUST specify that the dialog
// is an invisible child window
SetDlgCtrlID(nID);
CRect rect;
// force WS_CLIPSIBLINGS
// I also remove the titlebar. This means the resource can include a caption, which
// will be used when the frame is floating.
ModifyStyle(WS_CAPTION, WS_CLIPSIBLINGS);
if (!ExecuteDlgInit(lpszTemplateName))
return FALSE;
// m_sizeDefault isn't actually used by the COXSizeDialogBar, but since it's public, it
// seemed sensible to keep it available. Otherwise it might be difficult to get hold
// of the original size of the dialog (as specified in the resource file).
//GetWindowRect(&rect);
GetClientRect(&rect);
m_sizeDefault = rect.Size(); // set fixed size
// Move to position 0,0
// NB: size not forced to zero, as this can affect resizing if bar is
// immediately docked
SetWindowPos(NULL, 0, 0, 0, 0,
SWP_NOZORDER|SWP_NOACTIVATE|SWP_SHOWWINDOW|SWP_NOSIZE|SWP_FRAMECHANGED);
// set all the sizes to be the default after the positioning done above
m_VertDockSize = m_sizeDefault;
m_HorzDockSize = m_sizeDefault;
m_FloatSize = m_sizeDefault;
// if auto-sizing, store the rectangles of all the child windows.
if(m_Style & SZBARF_DLGAUTOSIZE)
{
m_GadgetResizeHandle = CreateGadgetResizeHandle(this);
}
return TRUE;
}
// need to paint the background...
BOOL COXSizeDialogBar::OnEraseBkgnd(CDC* pDC)
{
return COXSizeControlBar::OnEraseBkgnd(pDC);
}
void COXSizeDialogBar::OnUpdateCmdUI(CFrameWnd* pTarget, BOOL bDisableIfNoHndler)
{
COXSizeControlBar::OnUpdateCmdUI(pTarget,bDisableIfNoHndler);
UpdateDialogControls(pTarget, bDisableIfNoHndler);
}
void COXSizeDialogBar::OnSizedOrDocked(int cx, int cy, BOOL bFloating, int flags)
{
COXSizeControlBar::OnSizedOrDocked(cx, cy, bFloating, flags);
if (cx == 0 || cy == 0)
return;
// if auto-sizing, go thru and reposition all the controls.
if (m_Style & SZBARF_DLGAUTOSIZE)
{
CRect rectClient;
GetClientRect(&rectClient);
ResizeGadgetsOnWindow(m_GadgetResizeHandle, rectClient.Width(),
rectClient.Height());
}
}
/////////////////////////////////////////////////////////////////////////////
// Gadget resizing functions - used to resize all the child windows of a dialog
// bar above. Routines extracted as they may be more used in general
// For a given window, creates an array of the child windows, that can be used
// for resizing later on.
GADGETRESIZEHANDLE CreateGadgetResizeHandle(CWnd* pWnd)
{
CPtrArray* pArray = new CPtrArray;
// 1st element of the array stores the client rectangle of the given window
RECT_AND_HWND* pRectWnd = new RECT_AND_HWND;
pWnd->GetClientRect(&(pRectWnd->m_rect));
pRectWnd->m_hWnd = NULL;
pArray->Add(pRectWnd);
TCHAR szClassName[64];
for (HWND hWndChild = ::GetTopWindow(pWnd->m_hWnd); hWndChild != NULL;
hWndChild = ::GetNextWindow(hWndChild, GW_HWNDNEXT))
{
RECT_AND_HWND* pRectWnd = new RECT_AND_HWND;
pRectWnd->m_hWnd = hWndChild;
GetClassName(pRectWnd->m_hWnd, szClassName, 64);
::GetWindowRect(hWndChild, &(pRectWnd->m_rect));
pWnd->ScreenToClient(&(pRectWnd->m_rect));
// if it's a drop down combo box, then we set bottom -ve to indicate
// we should keep the height fixed. Otherwise we might find that the drop
// down size gets stupidly small.
if (_tcscmp(szClassName, _T("ComboBox")) == 0 &&
(GetWindowLongPtr(hWndChild, GWL_STYLE) & (CBS_DROPDOWN | CBS_DROPDOWNLIST)) )
{
pRectWnd->m_rect.bottom = - (pRectWnd->m_rect.bottom - pRectWnd->m_rect.top);
}
pArray->Add(pRectWnd);
}
return (GADGETRESIZEHANDLE) pArray;
}
// deletes the underlying array and it's elements
void DestroyGadgetResizeHandle(GADGETRESIZEHANDLE Handle)
{
CPtrArray* pArray = (CPtrArray*)Handle;
if (pArray != NULL)
{
for (int i = PtrToInt(pArray->GetUpperBound()); i >= 0; i--)
delete ((RECT_AND_HWND*)pArray->GetAt(i));
delete pArray;
}
}
// Resizes all the gadgets in an array to match the new size.
// Generally called from an OnSize routine (or the like)
void ResizeGadgetsOnWindow(GADGETRESIZEHANDLE Handle, int cx, int cy)
{
CPtrArray* pArray = (CPtrArray*)Handle;
if (pArray == NULL || cx == 0 || cy == 0)
return;
ASSERT(pArray->GetSize() > 0); // must be at least one element in the array
// if auto-sizing, go thru and reposition all the controls.
CSize sizeOrig = ((RECT_AND_HWND*)pArray->GetAt(0))->m_rect.Size();
if(sizeOrig.cx==0)
sizeOrig.cx=1;
if(sizeOrig.cy==0)
sizeOrig.cy=1;
for (int i = 1; i < pArray->GetSize(); i++)
{
RECT_AND_HWND* pRectWnd = (RECT_AND_HWND*)pArray->GetAt(i);
CRect newRect = pRectWnd->m_rect;
newRect.top = newRect.top * cy / sizeOrig.cy;
newRect.left = newRect.left * cx / sizeOrig.cx;
newRect.right = newRect.right * cx / sizeOrig.cx;
// if bottom is < 0, then keep it fixed height - used for combo boxes
// where we don't really want to resize most of them...
if (newRect.bottom < 0)
newRect.bottom = newRect.top - newRect.bottom;
else
newRect.bottom = newRect.bottom * cy / sizeOrig.cy;
::SetWindowPos(pRectWnd->m_hWnd, NULL,
newRect.left, newRect.top, newRect.Width(), newRect.Height(),
SWP_NOZORDER);
}
}
#ifndef _AFX_NO_OCC_SUPPORT
LRESULT COXSizeDialogBar::HandleInitDialog(WPARAM, LPARAM)
{
Default(); // allow default to initialize first (common dialogs/etc)
// get extension data - for backward compatibility with existing MRCEXT,
// this can't be in the base class itself.
// create OLE controls
COccManager* pOccManager = afxOccManager;
if ((pOccManager != NULL) && (m_pOccDialogInfo != NULL))
{
if (!pOccManager->CreateDlgControls(this, m_lpszTemplateName, m_pOccDialogInfo))
{
TRACE0("Warning: CreateDlgControls failed during dialog bar init.\n");
return FALSE;
}
}
BOOL bResult=OnInitDialog();
return bResult;
}
BOOL COXSizeDialogBar::SetOccDialogInfo(_AFX_OCC_DIALOG_INFO* pOccDialogInfo)
{
m_pOccDialogInfo = pOccDialogInfo;
return TRUE;
}
#endif