1291 lines
37 KiB
C++
Raw Normal View History

2001-01-01 00:00:00 +01:00
// ResizeDlg.cpp: implementation of the CResizeDlg class.
#include "pch.h"
#include "ResizeDlg.h"
#include "debug.h"
#include "persctl.h"
// #include "w32err.h" // #include "E:\nt\private\NTOS\w32\w32inc\w32err.h"
// #include "usercli.h" // #include "e:\nt\private\ntos\w32\ntuser\client\usercli.h"
// #include "resource.h"
// #include "E:\nt\private\NTOS\w32\w32inc\w32err.h"
#define MIN_COL_SPACE 4
#define MIN_ROW_SPACE 4
void* __cdecl operator new(size_t n)
{
// return malloc(n);
return GlobalAlloc(GPTR, n);
}
void __cdecl operator delete(void* p)
{
// free(p);
GlobalFree(p);
}
extern "C" {
LPVOID __cdecl MakeAResizeDlg(int id, HANDLE h)
{
return new CResizeDlg(id, NULL, (HINSTANCE) h);
}
LRESULT ResizeDlgMessage(LPVOID pObject, HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
return ((CResizeDlg*) pObject)->DlgProc(hwnd, message, wParam, lParam);
}
};
// Construction/Destruction
CResizeDlg::CResizeDlg(int DlgID, HWND hWndParent, HINSTANCE hInst)
: BASECLASS(DlgID, hWndParent, hInst)
{
SetAnnotate(FALSE);
SetRowWeight(0);
SetColWeight(0);
m_hwndGripper = NULL;
}
CResizeDlg::~CResizeDlg()
{
}
BOOL CALLBACK CResizeDlg::DlgProc(HWND hDlg, UINT uMessage, WPARAM wParam, LPARAM lParam)
{
switch (uMessage)
{
case WM_NCHITTEST:
{
// Because we always turn on the resize frame, we must always hit test.
// if( (GetRowWeight() !=0 ) || (GetColWeight() != 0 ) )
{
// call def window proc to see what he wants to do
LONG lRes = HitTest(DefWindowProc(hDlg, uMessage, wParam, lParam));
if (lRes != (HTERROR - 1))
{
SetWindowLong(hDlg, DWL_MSGRESULT, lRes);
return TRUE;
}
}
}
break;
case WM_WINDOWPOSCHANGING:
if ((GetRowWeight() != 0) || (GetColWeight() != 0))
DoChangePos((WINDOWPOS*) lParam);
break;
case WM_ERASEBKGND:
/*
if( (GetRowWeight() !=0 ) || (GetColWeight() != 0 ) )
{
HDC hdc=(HDC)wParam;
RECT rcWindow;
GetClientRect(hDlg, &rcWindow);
int g_cxGrip = GetSystemMetrics( SM_CXVSCROLL );
int g_cyGrip = GetSystemMetrics( SM_CYHSCROLL );
rcWindow.left = rcWindow.right - g_cxGrip; // pWState->x_VSBArrow;
rcWindow.top = rcWindow.bottom - g_cyGrip; // pWState->y_HSBArrow;
DrawFrameControl(hdc, &rcWindow, DFC_SCROLL, DFCS_SCROLLSIZEGRIP);
}
*/
break;
case WM_INITDIALOG:
SetWindow(hDlg);
DoInitDialog();
// Re-adjusts the dialogs to what we think they should be
// breaks some apps who are completely owner draw.
if ((GetRowWeight() != 0) || (GetColWeight() != 0))
{
AddGripper(); // need to sit on the size meesage too.
RECT r;
GetWindowRect(hDlg, &r);
SetWindowPos(
NULL, NULL, 0, 0, r.right - r.left, r.bottom - r.top,
SWP_NOACTIVATE | SWP_NOCOPYBITS | SWP_NOMOVE | SWP_NOOWNERZORDER |
SWP_NOREDRAW | SWP_NOZORDER);
}
return TRUE;
break;
case WM_SIZE:
if ((GetRowWeight() != 0) || (GetColWeight() != 0))
{
// Don't try to re-adjust to the size when initially shown.
if (wParam == SIZE_RESTORED)
{
WINDOWPOS pos = { NULL, NULL, 0, 0, LOWORD(lParam), HIWORD(lParam),
SWP_NOACTIVATE | SWP_NOCOPYBITS | SWP_NOMOVE | SWP_NOOWNERZORDER |
SWP_NOREDRAW | SWP_NOSENDCHANGING | SWP_NOZORDER };
DoChangePos(&pos);
ResizeControls(LOWORD(lParam), HIWORD(lParam));
}
}
break;
case WM_PAINT:
Annotate();
break;
}
return FALSE;
}
// Walks all the controls, finds their edges,
// attatches them to their edges/guides.
void CResizeDlg::WalkControls()
{
m_ParentInfo.Init(GetWindow());
FindControls();
m_ParentInfo.DeterminBorders(&m_ControlList);
MakeAttatchments();
FindCommonGuides();
SpecialRowCol();
}
// Walk the dialog
// build structures of what we think the relationships of the controls is.
void CResizeDlg::FindControls()
{
HWND hCurrent;
HWND hFirst;
hCurrent = hFirst = ::GetWindow(GetWindow(), GW_CHILD);
TRACE(L"FindControls on 0x%0x\n", GetWindow());
TRACE(L"Parent size is %d,%d by %d,%d\n", m_ParentInfo.GetLeft(), m_ParentInfo.GetTop(), m_ParentInfo.GetRight(), m_ParentInfo.GetBottom());
if (hFirst)
{
do {
CResizeControl * pC = new CResizeControl(hCurrent, m_ParentInfo);
if (pC->Valid())
{
// Make sure the control is wihin the bounds of our parent.
RECT r = pC->GetLocation();
TRACE(L"Control size is %d,%d by %d,%d\n",
r.left,
r.top,
r.right,
r.bottom);
if ((r.right > m_ParentInfo.GetRight()) ||
(r.bottom > m_ParentInfo.GetBottom()) ||
(r.top < m_ParentInfo.GetTop()) ||
(r.left < m_ParentInfo.GetLeft()))
{
TRACE(L"Punting this control %s\n", pC->GetClassName());
delete pC; // we don't play with these.
}
else
m_ControlList.Append(pC);
}
else
delete pC;
} while (hCurrent = ::GetWindow(hCurrent, GW_HWNDNEXT));
}
}
// We have data backing each control now.
// walk it and have it initialize itself.
void CResizeDlg::FindBorders()
{
}
// Now we have determined the borders on the dialog, see
// if any controls can make assumptions about their individual
// attatchments.
void CResizeDlg::MakeAttatchments()
{
CResizeControl * pC;
int i = 0;
while (pC = m_ControlList.GetControl(i++))
pC->DeterminLeftAttatchments();
i = 0;
while (pC = m_ControlList.GetControl(i++))
pC->DeterminTopAttatchments();
i = 0;
while (pC = m_ControlList.GetControl(i++))
pC->DeterminRightAttatchments();
i = 0;
while (pC = m_ControlList.GetControl(i++))
pC->DeterminBottomAttatchments();
i = 0;
while (pC = m_ControlList.GetControl(i++))
pC->SetControlAssociations();
}
void CResizeDlg::ResizeControls(WORD width, WORD height)
{
int iSpecialRow = GetNumRows() - 1;
int iSpecialCol = GetNumCols() - 1;
// Add free space
if (GetColWeight() > 0)
{
int FreeW = width - m_Cols[GetNumCols()].Pos - m_ParentInfo.GetRightBorder();
if (FreeW != 0)
{
int iPadding = 0;
int iPad = FreeW / GetColWeight();
for (int fi = 0; fi <= GetNumCols(); fi++)
{
m_Cols[fi].Pos += iPadding;
if (m_Cols[fi].iFixed >= 0)
iPadding += iPad * m_Cols[fi].iWeight;
}
}
}
// Add free row.
if (GetRowWeight() > 0)
{
int Free = height - m_Rows[GetNumRows()].Pos - m_ParentInfo.GetBottomBorder();
if (Free != 0)
{
int iPadding = 0;
int iPad = Free / GetRowWeight();
for (int fi = 0; fi <= GetNumRows(); fi++)
{
m_Rows[fi].Pos += iPadding;
if (m_Rows[fi].iFixed >= 0)
iPadding += iPad * m_Rows[fi].iWeight;
}
}
}
// Now setup the information for all of the controls, as to which cell they are in.
HDWP hdwp = BeginDeferWindowPos(m_ControlList.GetControlCount());
int i = 0;
CResizeControl * pC;
CConstraint * pCons;
while (pC = (CResizeControl *) m_ControlList.GetPointer(i++))
{
pCons = &(pC->m_Cons);
int x = m_Cols[pCons->GetCol()].Pos + pCons->GetPadLeft();
int y = m_Rows[pCons->GetRow()].Pos + pCons->GetPadTop();
int w, h;
BOOL bMove = true; BOOL bSize = false;
if (pC->IsGrowsWide())
{
w = m_Cols[pCons->GetCol() + pCons->GetColW()].Pos + pCons->GetPadRight() - x;
bSize = true;
}
else
w = pC->GetWidth();
if (pC->IsGrowsHigh())
{
h = m_Rows[pCons->GetRow() + pCons->GetRowH()].Pos + pCons->GetPadBottom() - y;
bSize = true;
}
else
h = pC->GetHeight();
// Here we special case the ComboBox - yuck.
if (lstrcmp(pC->GetClassName(), L"Button") == 0)
{
// Check box button is OK though.
int ibs = GetWindowStyle(pC->GetControl());
if ((ibs & 0xf) == BS_GROUPBOX)
{
// Force the width / height.
w = m_Cols[pCons->GetCol() + pCons->GetColW()].Pos + pCons->GetPadRight() - x;
h = m_Rows[pCons->GetRow() + pCons->GetRowH()].Pos + pCons->GetPadBottom() - y;
bSize = true;
}
}
// If they are in special row / columns we do something special to them.
if (m_SpecialCol.bSpecial && (pCons->GetCol() == iSpecialCol))
{
// alignment issues
if (m_SpecialCol.iAlignment == -1)
{
y = pC->GetTopGap();
}
else
if (m_SpecialCol.iAlignment == 1)
{
// Right aligned.
y = pC->GetTopGap() + height - m_SpecialCol.iMax - m_ParentInfo.GetTopBorder();
}
else
{
// Center aligned
y = pC->GetTopGap() + ((height - m_SpecialCol.iMax - m_ParentInfo.GetTopBorder()) / 2);
}
}
if (m_SpecialRow.bSpecial && (pCons->GetRow() == iSpecialRow))
{
// alignment issues
if (m_SpecialRow.iAlignment == -1)
{
x = pC->GetLeftGap();
}
else
if (m_SpecialRow.iAlignment == 1) // right aligned.
{
x = pC->GetLeftGap() + width - m_SpecialRow.iMax - m_ParentInfo.GetRightBorder();
}
else
{
x = pC->GetLeftGap() + ((width - m_SpecialRow.iMax - m_ParentInfo.GetRightBorder()) / 2);
}
}
hdwp = DeferWindowPos(hdwp, pC->GetControl(), NULL,
x, y, w, h,
(bMove ? 0 : SWP_NOMOVE) | (bSize ? 0 : SWP_NOSIZE) | SWP_NOZORDER);
}
// Move the gripper
SetGripperPos(hdwp);
EndDeferWindowPos(hdwp);
}
// Tries to combine guides to be offsets from other guides.
void CResizeDlg::FindCommonGuides()
{
CEdge ** ppVert = m_ParentInfo.GetVerticalEdges();
CEdge ** ppHoriz = m_ParentInfo.GetHorizontalEdges();
// Work out which guides are used in columns.
int iCount, i;
iCount = m_ParentInfo.GetNumVert();
Sort(ppVert, iCount);
#ifdef _DEBUG
TRACE(L"Vertical edge information %d edges\n", iCount);
for (i = 0; i < iCount; i++)
{
CEdge * pEdge = ppVert[i];
TRACE(L"Edge %02d: Edge@%02d times as 0x%02x, position %08d, Guide@%03d\n",
i, pEdge->GetControlCount(),
pEdge->GetGuide()->Attatchment(),
pEdge->GetPosition(),
pEdge->GetGuide()->NumAttatchments()
);
}
#endif
iCount = m_ParentInfo.GetNumHoriz();
Sort(ppHoriz, iCount);
#ifdef _DEBUG
TRACE(L"Horiz edge information %d edges\n", iCount);
for (i = 0; i < iCount; i++)
{
CEdge * pEdge = ppHoriz[i];
CGuide * pGuide = pEdge->GetGuide();
TRACE(L"Edge %02d: Edge@%02d times as 0x%02x, position %08d, Guide@%03d\n", i,
pEdge->GetControlCount(),
pEdge->Attatchment(),
pGuide->GetPosition(),
pEdge->GetGuide()->NumAttatchments()
);
}
#endif
// Determin rows and columns
DeterminCols(ppVert, m_ParentInfo.GetNumVert());
DeterminRows(ppHoriz, m_ParentInfo.GetNumHoriz());
PlaceControls();
delete [] ppVert;
delete [] ppHoriz;
DeterminWeights();
}
// Sorts an array of edges.
void CResizeDlg::Sort(CEdge * *ppEdges, int iCount)
{
// Lame sort BB fix later.
int iInsert = 0;
while (iInsert < iCount)
{
int iSmallest = iInsert;
for (int iMatch = iInsert; iMatch < iCount; iMatch++)
{
if (ppEdges[iMatch]->GetPosition() < ppEdges[iSmallest]->GetPosition())
iSmallest = iMatch;
}
if (iSmallest > iInsert)
{
CEdge * pTemp = ppEdges[iInsert];
ppEdges[iInsert] = ppEdges[iSmallest];
ppEdges[iSmallest] = pTemp;
}
// TRACE(L"%02d is %08d\n", iInsert, ppEdges[iInsert]->GetPosition() );
iInsert++;
}
}
// State table kinda used to determin when a new col. is needed
// Prev This New Col?
// L L Yes, on this edge
// L R Yes, on this edge
// R L Yes, between these two edges
// R R Yes if last (no if on same guide)?
void CResizeDlg::DeterminCols(CEdge * * ppEdges, int iCount)
{
// First pass is just to work out positions of edges, and if those edges constitute Columns.
int i;
int iCols = 0;
int iLastGuide;
int iThisGuide;
int * iPos = new int[iCount]; // where the edges are
iPos[0] = ppEdges[0]->GetPosition(); // we always use the first edge.
int iLastPos = 0;
for (i = 1; i < iCount; i++)
{
iThisGuide = ppEdges[i]->Attatchment();
iLastGuide = ppEdges[i - 1]->Attatchment();
TRACE(L"Edge:%02d - Attatched as %02d\n", i, iThisGuide);
// Column between these two controls
if ((iLastGuide & RIGHT_AT) && (iThisGuide & LEFT_AT))
{
iCols++;
iPos[iCols] = ppEdges[i - 1]->GetPosition() + ((ppEdges[i]->GetPosition() - ppEdges[i - 1]->GetPosition()) / 2);
continue;
}
// If we're starting another left edge of a control, needs a new guide
if ((iThisGuide & LEFT_AT))
{
iCols++;
iPos[iCols] = ppEdges[i]->GetPosition();
continue;
}
// If this is the last right edge
if ((iThisGuide & RIGHT_AT) && ((i + 1) == iCount))
{
iCols++;
iPos[iCols] = ppEdges[i]->GetPosition();
continue; // just incase you add anytyhing below
}
}
// Second pass is to make up the column information
// we don't allow narrow colums, that is columns who are <2 appart.
TRACE(L"Column Widths are ...\n");
SetNumCols(iCols); // 0 through n are USED. Not n-1
m_Cols = new CHANNEL[iCols + 1];
m_Cols[0].Pos = iPos[0];
iLastPos = 0;
int iThisCol = 1;
for (int iThisPos = 1; iThisPos <= iCols; iThisPos++)
{
int iWidth = iPos[iThisPos] - iPos[iLastPos];
if (iWidth >= MIN_COL_SPACE)
{
m_Cols[iThisCol].Pos = iPos[iThisPos];
m_Cols[iThisCol - 1].Size = iWidth;
m_Cols[iThisCol - 1].iWeight = 0;
m_Cols[iThisCol - 1].iFixed = FALSE;
/*
TRACE(L"Col:%02d Width:%03d Pos:%03d\n",
iThisCol-1,
m_Cols[iThisCol-1].Size,
m_Cols[iThisCol-1].Pos);
*/
iLastPos = iThisPos;
iThisCol++;
}
else
{
// TRACE(L"Skipping col #%d as it's only %d wide\n",iThisPos,iWidth);
}
}
#ifdef _DEBUG
if ((iThisCol - 1) != iCols)
TRACE(L"Skipped %d rows\n", iThisCol - 1 - iCols);
#endif
SetNumCols(iThisCol - 1);
delete [] iPos;
}
// State table kinda used to determin when a new col. is needed
// Prev This New Col?
// L L Yes, on this edge
// L R Yes, on this edge
// R L Yes, between these two edges
// R R Yes if last (no if on same guide)?
void CResizeDlg::DeterminRows(CEdge * * ppEdges, int iCount)
{
int i;
int iRows = 0;
int iLastGuide;
int iThisGuide;
int * iPos = new int[iCount];
// brute force, each edge is a row.
iRows = 0;
iPos[0] = ppEdges[0]->GetPosition();
int iLastPos = 0;
for (i = 1; i < iCount; i++)
{
iThisGuide = ppEdges[i]->Attatchment();
iLastGuide = ppEdges[i - 1]->Attatchment();
TRACE(L"Edge:%02d - Attatched as %02d pos:%03d\n", i, iThisGuide, ppEdges[i]->GetPosition());
// row between these two controls
if ((iLastGuide & BOTTOM_AT) && (iThisGuide & TOP_AT))
{
iRows++;
iPos[iRows] = ppEdges[i - 1]->GetPosition() + ((ppEdges[i]->GetPosition() - ppEdges[i - 1]->GetPosition()) / 2);
continue;
}
// If we're starting another left edge of a control, needs a new guide
if ((iThisGuide & TOP_AT))
{
iRows++;
iPos[iRows] = ppEdges[i]->GetPosition();
continue;
}
// If this is the last right edge
if ((iThisGuide & BOTTOM_AT) && ((i + 1) == iCount))
{
iRows++;
iPos[iRows] = ppEdges[i]->GetPosition();
continue; // just incase you add anytyhing below
}
}
// Second pass is to make up the column information
// we don't allow narrow colums, that is columns who are <2 appart.
TRACE(L"Rowumn Widths are ...\n");
SetNumRows(iRows); // 0 through n are USED. Not n-1
m_Rows = new CHANNEL[iRows + 1];
m_Rows[0].Pos = iPos[0];
iLastPos = 0;
int iThisRow = 1;
for (int iThisPos = 1; iThisPos <= iRows; iThisPos++)
{
int iWidth = iPos[iThisPos] - iPos[iLastPos];
if (iWidth >= MIN_ROW_SPACE)
{
m_Rows[iThisRow].Pos = iPos[iThisPos];
m_Rows[iThisRow - 1].Size = iWidth;
m_Rows[iThisRow - 1].iWeight = 0;
m_Rows[iThisRow - 1].iFixed = FALSE;
/*
TRACE(L"Row:%02d Width:%03d Pos:%03d\n",
iThisRow-1,
m_Rows[iThisRow-1].Size,
m_Rows[iThisRow-1].Pos);
*/
iLastPos = iThisPos;
iThisRow++;
}
else
{
// TRACE(L"Skipping Row #%d as it's only %d wide\n",iThisPos,iWidth);
}
}
#ifdef _DEBUG
if ((iThisRow - 1) != iRows)
TRACE(L"Skipped %d rows\n", iThisRow - 1 - iRows);
#endif
SetNumRows(iThisRow - 1);
delete [] iPos;
}
// Draws the annotations on the dialog of where the column/rows are
void CResizeDlg::Annotate()
{
if (GetAnnotate() == false)
return;
HDC hdc = GetDC(GetWindow());
// Draw all the control edges on the screen.
// m_ParentInfo.Annotate( hdc );
// Now show the cols/rows
int iCount = GetNumRows();
int i;
RECT r;
GetWindowRect(GetWindow(), &r);
int iWidth = r.right - r.left;
int iHeight = r.bottom - r.top;
HPEN hFixedPen = CreatePen(PS_SOLID, 2, RGB(0x00, 0x00, 0xff));
HPEN hSizePen = CreatePen(PS_SOLID, 2, RGB(0x00, 0xff, 0x00));
HGDIOBJ holdPen = SelectObject(hdc, hFixedPen);
// Horizontal lines
for (i = 0; i <= iCount; i++)
{
if (m_Rows[i].iFixed >= 0)
SelectObject(hdc, hSizePen);
else
SelectObject(hdc, hFixedPen);
MoveToEx(hdc, 0, m_Rows[i].Pos, NULL);
LineTo(hdc, iWidth, m_Rows[i].Pos);
}
// Vertical lines
iCount = GetNumCols();
for (i = 0; i <= iCount; i++)
{
if (m_Cols[i].iFixed >= 0)
SelectObject(hdc, hSizePen);
else
SelectObject(hdc, hFixedPen);
MoveToEx(hdc, m_Cols[i].Pos, 0, NULL);
LineTo(hdc, m_Cols[i].Pos, iHeight);
}
SelectObject(hdc, holdPen);
DeleteObject(hFixedPen);
DeleteObject(hSizePen);
ReleaseDC(GetWindow(), hdc);
}
int CResizeDlg::FindRow(int pos)
{
int i = 0;
while (i <= GetNumRows())
{
if (m_Rows[i].Pos > pos)
return i - 1;
i++;
}
return GetNumRows();
}
int CResizeDlg::FindCol(int pos)
{
int i = 0;
while (i <= GetNumCols())
{
if (m_Cols[i].Pos > pos)
return i - 1;
i++;
}
return GetNumCols();
}
// Walks the rows/columns and determins if they are resizable.
void CResizeDlg::DeterminWeights()
{
int iColWeight = 0;
{
for (int fi = 0; fi <= GetNumCols(); fi++)
m_Cols[fi].iFixed < 0 ? 0 : iColWeight += m_Cols[fi].iWeight;
}
int iRowWeight = 0;
{
for (int fi = 0; fi <= GetNumRows(); fi++)
m_Rows[fi].iFixed < 0 ? 0 : iRowWeight += m_Rows[fi].iWeight;
}
SetColWeight(iColWeight);
SetRowWeight(iRowWeight);
}
// Passed in the current hit test, allows you to override it.
// return HTERROR -1 if we didn't deal with it.
LONG CResizeDlg::HitTest(LONG lCurrent)
{
#define WIDE 1
#define HIGH 2
int iThisDlg = (GetRowWeight() ? HIGH : 0) | (GetColWeight() ? WIDE : 0);
// TRACE(L"NC Hit Test %d - dlg is %d\n",lCurrent, iThisDlg);
switch (lCurrent)
{
case HTLEFT: // In the left border of a window
case HTRIGHT: // In the rigcase HT border of a window
if (iThisDlg == 0)
return HTNOWHERE;
if (iThisDlg & WIDE)
return lCurrent; // OK
return HTNOWHERE;
case HTTOP: // In the upper horizontal border of a window
case HTBOTTOM: // In the lower horizontal border of a window
if (iThisDlg == 0)
return HTNOWHERE;
if (iThisDlg & HIGH)
return lCurrent; // OK
return HTNOWHERE; // Can't make taller
case HTTOPLEFT: // In the upper-left corner of a window border
case HTTOPRIGHT: // In the upper rigcase HT corner of a window border
if (iThisDlg == 0)
return HTNOWHERE;
if ((iThisDlg & (HIGH | WIDE)) == (HIGH | WIDE))
return lCurrent;
if (iThisDlg & HIGH)
return HTTOP;
if (lCurrent == HTTOPLEFT)
return HTLEFT;
return HTRIGHT;
case HTGROWBOX: // In a size box (same as case HTSIZE)
if (iThisDlg == 0)
return HTNOWHERE;
if ((iThisDlg & (HIGH | WIDE)) == (HIGH | WIDE))
return lCurrent;
if (iThisDlg & HIGH)
return HTBOTTOM;
return HTRIGHT;
case HTBOTTOMLEFT: // In the lower-left corner of a window border
case HTBOTTOMRIGHT: // In the lower-rigcase HT corner of a window border
if (iThisDlg == 0)
return HTNOWHERE;
if ((iThisDlg & (HIGH | WIDE)) == (HIGH | WIDE))
return lCurrent;
if (iThisDlg & HIGH)
return HTBOTTOM;
if (lCurrent == HTBOTTOMRIGHT)
return HTRIGHT;
return HTLEFT;
}
return HTERROR - 1;
}
// Determins the location of the controls in the row/col space.
void CResizeDlg::PlaceControls()
{
// Now setup the information for all of the controls, as to which cell they are in.
int i = 0;
CResizeControl * pC;
CConstraint * pCons;
while (pC = (CResizeControl *) m_ControlList.GetPointer(i++))
{
int Row, Col, RowH, ColW;
RECT r = pC->GetLocation();
pCons = &(pC->m_Cons);
Row = FindRow(r.top);
RowH = FindRow(r.bottom) - Row + 1;
if (RowH + Row > GetNumRows())
RowH = GetNumRows() - Row;
Col = FindCol(r.left);
ColW = FindCol(r.right) - Col + 1;
if (ColW + Col > GetNumCols())
ColW = GetNumCols() - Col;
pCons->SetCol(Col);
pCons->SetRow(Row);
pCons->SetColW(ColW);
pCons->SetRowH(RowH);
// Now adjust the padding from the edges of the cell.
pCons->SetPadTop(r.top - m_Rows[Row].Pos);
pCons->SetPadBottom(r.bottom - m_Rows[Row + RowH].Pos);
pCons->SetPadLeft(r.left - m_Cols[Col].Pos);
pCons->SetPadRight(r.right - m_Cols[Col + ColW].Pos);
/*
IF you're worried that you got the dimentions wrong
TRACE(L"Component %03d [%06d] %s\n pos: l:%03d, r:%03d, t:%03d, b:%03d\nCell: l:%03d, r:%03d, t:%03d, b:%03d\n",
i, GetDlgCtrlID( pC->GetControl()), pC->GetClassName(), r.left, r.right, r.top, r.bottom,
m_Cols[pCons->GetCol()].Pos + pCons->GetPadLeft(),
m_Cols[pCons->GetCol()+pCons->GetColW()].Pos + pCons->GetPadRight(),
m_Rows[pCons->GetRow()].Pos + pCons->GetPadTop(),
m_Rows[pCons->GetRow()+pCons->GetRowH()].Pos + pCons->GetPadBottom() );
*/
TRACE(L"Component %03d [%06d] %s\n pos: Cell: %03d,%03d by %03d x %03d\n Padding:l:%03d, r:%03d, t:%03d, b:%03d\n",
i, GetDlgCtrlID(pC->GetControl()), pC->GetClassName(),
pCons->GetCol(), pCons->GetRow(), pCons->GetColW(), pCons->GetRowH(),
pCons->GetPadLeft(), pCons->GetPadRight(), pCons->GetPadTop(), pCons->GetPadBottom());
// Mark each column this control spans as gets wider.
int iCol = pCons->GetCol();
int ic = pCons->GetColW();
while (ic--)
{
if (pC->IsGrowsWide() == false)
m_Cols[iCol + ic].iFixed -= 1; // can't make wider
else
{
m_Cols[iCol + ic].iWeight++;
m_Cols[iCol + ic].iFixed += 2; // can make wider
}
}
ic = pCons->GetRowH();
int iRow = pCons->GetRow();
while (ic--)
{
if (pC->IsGrowsHigh() == false)
m_Rows[iRow + ic].iFixed -= 1; // can't make wider
else
{
m_Rows[iRow + ic].iWeight++;
m_Rows[iRow + ic].iFixed += 2; // can make wider
}
}
}
}
// Determins if we can actually change size to that asked for.
void CResizeDlg::DoChangePos(WINDOWPOS * lpwp)
{
if ((lpwp->flags & SWP_NOSIZE) == FALSE)
{
// We're being sized - size in screen area (ie. included title bar)
// m_ParentInfo EXCLUDES title bar.
RECT r;
GetWindowRect(GetWindow(), &r);
if (GetRowWeight() <= 0)
lpwp->cy = r.bottom - r.top;
if (GetColWeight() <= 0)
lpwp->cx = r.right - r.left;
DIMENSION dMin = m_ParentInfo.GetMinimumSize();
if (lpwp->cx < dMin.Width)
lpwp->cx = dMin.Width;
if (lpwp->cy < dMin.Height)
lpwp->cy = dMin.Height;
}
}
void CResizeDlg::DoInitDialog()
{
AddToSystemMenu();
WalkControls();
ResizeControls((WORD) m_ParentInfo.GetWidth(), (WORD) m_ParentInfo.GetHeight());
}
// Adds an annotate option to the system menu.
void CResizeDlg::AddToSystemMenu()
{
/*
// Get the system menu - add an annotate option to it?
HMENU hm=GetSystemMenu(GetWindow(), false);
TCHAR szAnnotate[128];
LoadString( GetInstance(), IDS_ANNOTATE, szAnnotate, 128);
MENUITEMINFO minfo={
sizeof(MENUITEMINFO),
MIIM_ID | MIIM_TYPE,
MFT_STRING,
0,
IDS_ANNOTATE, // ID
NULL, // SubMenu
NULL, // Checked
NULL, // Unchecked
0, // Item data - app specific
szAnnotate, // Content of the menu item
lstrlen(szAnnotate)+1// Length of menu item data
};
InsertMenuItem( hm, -1, TRUE, &minfo);
*/
}
void CResizeDlg::AddGripper()
{
int g_cxGrip = GetSystemMetrics(SM_CXVSCROLL);
int g_cyGrip = GetSystemMetrics(SM_CYHSCROLL);
RECT rc;
GetClientRect(GetWindow(), &rc);
m_hwndGripper = CreateWindow(TEXT("Scrollbar"),
NULL,
WS_VISIBLE | WS_CHILD | WS_CLIPSIBLINGS |
WS_CLIPCHILDREN | SBS_BOTTOMALIGN | SBS_SIZEGRIP |
SBS_SIZEBOXBOTTOMRIGHTALIGN,
rc.right - g_cxGrip,
rc.bottom - g_cyGrip,
g_cxGrip,
g_cyGrip,
GetWindow(),
(HMENU) -1,
(HINSTANCE) GetWindowLong(GetWindow(), GWL_HINSTANCE), // g_hinst,
NULL);
}
HDWP CResizeDlg::SetGripperPos(HDWP hdwp)
{
if (m_hwndGripper != NULL)
{
int g_cxGrip = GetSystemMetrics(SM_CXVSCROLL);
int g_cyGrip = GetSystemMetrics(SM_CYHSCROLL);
RECT rc;
GetClientRect(GetWindow(), &rc);
return DeferWindowPos(hdwp, m_hwndGripper, NULL,
rc.right - g_cxGrip,
rc.bottom - g_cyGrip,
g_cxGrip,
g_cyGrip,
SWP_NOZORDER | SWP_NOSIZE);
}
else
return hdwp;
}
// Construction/Destruction
CScaleDlg::CScaleDlg(int DlgID, HWND hWndParent, HINSTANCE hInst)
: BASECLASS(DlgID, hWndParent, hInst)
{
}
CScaleDlg::~CScaleDlg()
{
}
// Multiply the positions as a result of what they are now.
void CScaleDlg::ResizeControls(WORD width, WORD height)
{
// Perhaps we just scale the fontsize information too?
int OrigW = m_ParentInfo.GetRightBorder();
OrigW = m_ParentInfo.GetWidth();
int OrigH = m_ParentInfo.GetBottomBorder();
OrigH = m_ParentInfo.GetHeight();
// SetDialogFont
HFONT hFont = (HFONT) SendMessage(GetWindow(), WM_GETFONT, 0, 0);
LOGFONT lf;
GetObject((HGDIOBJ) hFont, sizeof(lf), &lf);
int scalew = width * 100 / OrigW;
int scaleh = height * 100 / OrigH;
int scale = scalew;
if (scalew < scaleh)
scale = scaleh;
lf.lfHeight = m_dwInitFontSize * scale / 100;
HFONT hNewFont = CreateFontIndirect(&lf);
HWND hCurrent;
HWND hFirst;
hCurrent = hFirst = ::GetWindow(GetWindow(), GW_CHILD);
if (hFirst)
{
do {
SendMessage(hCurrent, WM_SETFONT, (WPARAM) hNewFont, 1);
} while (hCurrent = ::GetWindow(hCurrent, GW_HWNDNEXT));
}
// newX=origX * width / origParentWidth
// Now setup the information for all of the controls, as to which cell they are in.
HDWP hdwp = BeginDeferWindowPos(m_ControlList.GetControlCount() + 1); // 1 for the gripper
int i = 0;
CResizeControl * pC;
while (pC = (CResizeControl *) m_ControlList.GetPointer(i++))
{
int x = pC->GetLeftGap(); // GetLeftEdge()->GetPosition();
int y = pC->GetTopGap(); // GetTopEdge()->GetPosition();
int w = OrigW - pC->GetRightGap() - x; // GetRightEdge()-GetPosition() - x;
int h = OrigH - pC->GetBottomGap() - y; // BottomEdge()-GetPosition() -y;
int newx = x * width / OrigW;
int newy = y * height / OrigH;
int neww = w * width / OrigW;
int newh = h * height / OrigH;
BOOL bMove = false;
if ((newx != x) || (newy != y))
bMove = true;
BOOL bSize = false;
if ((newh != h) || (neww != w))
bSize = true;
hdwp = DeferWindowPos(hdwp, pC->GetControl(), NULL, newx, newy, neww, newh, (bMove ? 0 : SWP_NOMOVE) | (bSize ? 0 : SWP_NOSIZE) | SWP_NOZORDER);
}
// Move the gripper
SetGripperPos(hdwp);
EndDeferWindowPos(hdwp);
}
void CScaleDlg::DeterminWeights()
{
SetRowWeight(1);
SetColWeight(1);
HFONT hFont = (HFONT) SendMessage(GetWindow(), WM_GETFONT, 0, 0);
LOGFONT lf;
GetObject(hFont, sizeof(lf), &lf);
m_dwInitFontSize = lf.lfHeight;
}
void CScaleDlg::DoChangePos(WINDOWPOS * lpwp)
{
// Lock the apsect ratio.
if ((lpwp->flags & SWP_NOSIZE) == FALSE)
{
if (dwLastCX != lpwp->cx)
dwLastCY = lpwp->cy = (lpwp->cx * m_ParentInfo.GetHeight()) / m_ParentInfo.GetWidth();
if (dwLastCY != lpwp->cy)
dwLastCX = lpwp->cx = (lpwp->cy * m_ParentInfo.GetWidth()) / m_ParentInfo.GetHeight();
}
}
void CResizeDlg::DeterminNumberOfControls()
{
int iControlCount = 0;
HWND hCurrent;
HWND hFirst;
hCurrent = hFirst = ::GetWindow(GetWindow(), GW_CHILD);
if (hFirst)
{
do {
iControlCount++;
} while (hCurrent = ::GetWindow(hCurrent, GW_HWNDNEXT));
}
m_ControlCount = iControlCount;
}
///
// Looks for the last row/col being full of buttons.
///
void CResizeDlg::SpecialRowCol()
{
TRACE("There are %d rows, and %d columns\n", GetNumRows(), GetNumCols());
// Walk the controls, find the row/col they are in.
BOOL bSpecialRow = TRUE;
BOOL bSpecialCol = TRUE;
int iNumRows = GetNumRows() - 1;
int iNumCols = GetNumCols() - 1;
// It is a special row if all the heights are the same
// it is a special col if all the widths are the same
int iRowHeight = 0;
int iColWidth = 0;
// It's a row/col if there is more than one control there
int iRowCount = 0;
int iColCount = 0;
// We remember the bounds of the rows/cols
// left/right is the left of the left button, and the right of the right
// top/bottom is the top of the topmost, and the bottom of the bottom most.
RECT bounds; // this is the
bounds.left = m_ParentInfo.GetWidth();
bounds.right = 0;
bounds.top = m_ParentInfo.GetHeight();
bounds.bottom = 0;
int i = 0;
CResizeControl * pC;
CConstraint * pCons;
while (pC = (CResizeControl *) m_ControlList.GetPointer(i++))
{
pCons = &(pC->m_Cons);
// Column work (widths same)
if (bSpecialCol)
{
if (((pCons->GetCol() == iNumCols) || (pCons->GetCol() + pCons->GetColW() > iNumCols)))
{
if (iColWidth == 0)
iColWidth = pC->GetWidth();
if (pC->GetWidth() != iColWidth)
bSpecialCol = FALSE;
iColCount++;
}
// If this item is wholy in this column
if (pCons->GetCol() == iNumCols)
{
RECT r = pC->GetLocation();
if (r.top < bounds.top)
bounds.top = r.top;
if (r.bottom > bounds.bottom)
bounds.bottom = r.bottom;
}
}
if (bSpecialRow)
{
if ((pCons->GetRow() == iNumRows) || (pCons->GetRow() + pCons->GetRowH() > iNumRows))
{
if (iRowHeight == 0)
iRowHeight = pC->GetHeight();
if (pC->GetHeight() != iRowHeight)
bSpecialRow = FALSE;
iRowCount++;
}
// If this item is wholy in this row
if (pCons->GetRow() == iNumRows)
{
RECT r = pC->GetLocation();
if (r.left < bounds.left)
bounds.left = r.left;
if (r.right > bounds.right)
bounds.right = r.right;
}
}
if ((bSpecialCol == FALSE) && (bSpecialRow == FALSE))
break;
}
m_SpecialRow.bSpecial = iRowCount > 1 ? bSpecialRow : FALSE;
m_SpecialCol.bSpecial = iColCount > 1 ? bSpecialCol : FALSE;
// Check the row alignment.
if (m_SpecialRow.bSpecial)
{
int lGap = bounds.left - m_ParentInfo.GetLeftBorder();
int rGap = m_ParentInfo.GetWidth() - m_ParentInfo.GetRightBorder() - bounds.right;
TRACE("Constraits on the special row are: left %d, right %d\n", bounds.left, bounds.right);
TRACE("Parent info is: left %d, right %d\n", m_ParentInfo.GetLeftBorder(), m_ParentInfo.GetWidth() - m_ParentInfo.GetRightBorder());
TRACE("Gaps are: left %d, right %d\n", lGap, rGap);
int GapDiff = lGap - rGap;
m_SpecialRow.bSpecial = TRUE;
m_SpecialRow.iMin = bounds.left;
m_SpecialRow.iMax = bounds.right;
if (GapDiff < -10)
{
TRACE("Probably a left aligned thing\n");
m_SpecialRow.iAlignment = -1;
}
else
if (GapDiff > 10)
{
TRACE(" Probably a right aligned thing\n");
m_SpecialRow.iAlignment = 1;
}
else
{
TRACE(" Probably a centered thing\n");
m_SpecialRow.iAlignment = 0;
}
m_SpecialRow.iDiff = GapDiff;
}
// Check the Col alignment.
if (m_SpecialCol.bSpecial)
{
int tGap = bounds.top - m_ParentInfo.GetTopBorder();
int bGap = m_ParentInfo.GetHeight() - m_ParentInfo.GetBottomBorder() - bounds.bottom;
TRACE("Constraits on the special Col are: top %d, bottom %d\n", bounds.top, bounds.bottom);
TRACE("Parent info is: top %d, bottom %d\n", m_ParentInfo.GetTopBorder(), m_ParentInfo.GetHeight() - m_ParentInfo.GetBottomBorder());
TRACE("Gaps are: top %d, bottom %d\n", tGap, bGap);
int GapDiff = tGap - bGap;
m_SpecialCol.iMin = bounds.top;
m_SpecialCol.iMax = bounds.bottom;
if (GapDiff < -10)
{
TRACE("Probably a left aligned thing\n");
m_SpecialCol.iAlignment = -1;
}
else
if (GapDiff > 10)
{
TRACE(" Probably a right aligned thing\n");
m_SpecialCol.iAlignment = 1;
}
else
{
TRACE(" Probably a centered thing\n");
m_SpecialCol.iAlignment = 0;
}
m_SpecialCol.iDiff = GapDiff;
}
}