// 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; } }