📄 cdxcdynamicwnd.cpp
字号:
// cdxCDynamicWnd.cpp: implementation of the cdxCDynamicWnd class.////////////////////////////////////////////////////////////////////////#include "stdafx.h"#include "cdxCDynamicWnd.h"#include "cdxCSizeIconCtrl.h"#ifdef _DEBUG#undef THIS_FILEstatic char THIS_FILE[]=__FILE__;#define new DEBUG_NEW#endif#pragma warning(disable: 4100)#pragma warning(disable: 4706)IMPLEMENT_DYNAMIC(cdxCDynamicLayoutInfo,CObject);//////////////////////////////////////////////////////////////////////// cdxCDynamicWnd::Position////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// Positioning engine///////////////////////////////////////////////////////////////////////* * Standard Controller's Position() routine * This has the same functionality as known from the former * cdxCDynamicControlsManager class. * * One exception is the new "szMin" property which allows * the class to "hide" the control if it becomes too small * (it will be moved outside the client area). */void cdxCDynamicWnd::Position::Apply(HWND hwnd, CRect & rectNewPos, const cdxCDynamicLayoutInfo & li) const{ if(li.m_bUseScrollPos) { rectNewPos.left = left - li.m_pntScrollPos.x; rectNewPos.right = right - li.m_pntScrollPos.x; rectNewPos.top = top - li.m_pntScrollPos.y; rectNewPos.bottom = bottom - li.m_pntScrollPos.y; if(li.m_szDelta.cx >= 0) { rectNewPos.left += (m_Bytes[X1] * li.m_szDelta.cx) / 100; rectNewPos.right += (m_Bytes[X2] * li.m_szDelta.cx) / 100; } if(li.m_szDelta.cy >= 0) { rectNewPos.top += (m_Bytes[Y1] * li.m_szDelta.cy) / 100; rectNewPos.bottom += (m_Bytes[Y2] * li.m_szDelta.cy) / 100; } } else { rectNewPos.left = left + (m_Bytes[X1] * li.m_szDelta.cx) / 100; rectNewPos.right = right + (m_Bytes[X2] * li.m_szDelta.cx) / 100; rectNewPos.top = top + (m_Bytes[Y1] * li.m_szDelta.cy) / 100; rectNewPos.bottom = bottom + (m_Bytes[Y2] * li.m_szDelta.cy) / 100; } if(rectNewPos.left + m_szMin.cx >= rectNewPos.right) { rectNewPos.right = -10; rectNewPos.left = rectNewPos.right - m_szMin.cx; } if(rectNewPos.top + m_szMin.cy >= rectNewPos.bottom) { rectNewPos.bottom = -10; rectNewPos.top = rectNewPos.bottom - m_szMin.cy; }}//////////////////////////////////////////////////////////////////////// cdxCDynamicWnd//////////////////////////////////////////////////////////////////////const CSize cdxCDynamicWnd::M_szNull(0,0);const cdxCDynamicWnd::SBYTES cdxCDynamicWnd::TopLeft = { 0,0,0,0 }, cdxCDynamicWnd::TopRight = { 100,0,100,0 }, cdxCDynamicWnd::BotLeft = { 0,100,0,100 }, cdxCDynamicWnd::BotRight = { 100,100,100,100 };//////////////////////////////////////////////////////////////////////// construction///////////////////////////////////////////////////////////////////////* * construction */cdxCDynamicWnd::cdxCDynamicWnd(Freedom fd, UINT nFlags): m_pWnd(NULL), m_iDisabled(0), m_Freedom(fd), m_szInitial(M_szNull), m_szMin(0,0), m_szMax(0,0), m_bUseScrollPos(false), m_pSizeIcon(NULL), m_idSizeIcon(AFX_IDW_SIZE_BOX), m_nMyTimerID(0), m_nFlags(nFlags){}//////////////////////////////////////////////////////////////////////// control work///////////////////////////////////////////////////////////////////////* * AddSzControl() * -------------- * Add a control that will react on changes to the parent window's size. * hwnd - the child control. * pos - describes what to do at all. * bReposNow - true to immediately make the control change its position * if necessary, false if not * In the latter case you may like to call Layout() afterwards. * * returns false if an invalid window has been passed to this funciton. */bool cdxCDynamicWnd::AddSzControl(HWND hwnd, const Position & pos, bool bReposNow){ if(!IsWindow()) { ASSERT(IsWindow()); return false; // NO assert if hwnd is invalid } if(!::IsWindow(hwnd)) { TRACE(_T("*** NOTE[cdxCDynamicWnd::AddSzControl(HWND,const Position &,bool)]: Handle 0x%lx is not a valid window.\n"),(DWORD)hwnd); return false; } m_Map.SetAt(hwnd,pos); if(bReposNow) UpdateControlPosition(hwnd); return true;}/* * AllControls() * ------------- * Apply positioning to all controls of the window. * bytes - positioning data * bOverwrite - overwrite any existing positioning data. * bReposNow - true to immediately make the control change its position * if necessary, false if not * In the latter case you may like to call Layout() afterwards. */void cdxCDynamicWnd::AllControls(const SBYTES & bytes, bool bOverwrite, bool bReposNow){ if(!IsWindow()) { ASSERT(false); return; } Position pos; UINT nCnt = 0; for(HWND hwnd = ::GetWindow(m_pWnd->m_hWnd,GW_CHILD); hwnd; hwnd = ::GetNextWindow(hwnd,GW_HWNDNEXT)) { if(bOverwrite || !m_Map.Lookup(hwnd,pos)) if(AddSzControl(hwnd,bytes,false)) ++nCnt; } if(nCnt && bReposNow) Layout();}/* * RemSzControl() * -------------- * Removes a control from the internal list. * The control will remain at its initial position if bMoveToInitialPos is false * Returns false if an error occured. */bool cdxCDynamicWnd::RemSzControl(HWND hwnd, bool bMoveToInitialPos){ if(!::IsWindow(hwnd) || !IsWindow()) return false; if(bMoveToInitialPos) { Position pos; if(!m_Map.Lookup(hwnd,pos)) return false; VERIFY( ::SetWindowPos(hwnd,HWND_TOP, pos.left,pos.top,pos.Width(),pos.Height(), SWP_NOACTIVATE|SWP_NOOWNERZORDER|SWP_NOZORDER) ); } return m_Map.RemoveKey(hwnd) != FALSE;}/* * UpdateControlPosition() * ======================= * Move control to its desired position. * returns false if HWND is not valid. */bool cdxCDynamicWnd::UpdateControlPosition(HWND hwnd){ if(!IsWindow()) { ASSERT(IsWindow()); return false; // NO assert if hwnd is invalid } if(!::IsWindow(hwnd)) { TRACE(_T("*** NOTE[cdxCDynamicWnd::UpdateControlPosition()]: Handle 0x%lx is not a valid window.\n"),(DWORD)hwnd); return false; } cdxCDynamicLayoutInfo *pli = DoCreateLayoutInfo(); ASSERT(pli != NULL); if(!pli || !pli->IsInitial()) { try { CRect rectNew; WINDOWPLACEMENT wpl; wpl.length = sizeof(WINDOWPLACEMENT); VERIFY(::GetWindowPlacement(hwnd,&wpl) ); rectNew = wpl.rcNormalPosition; if(DoMoveCtrl(hwnd,::GetDlgCtrlID(hwnd),rectNew,*pli) && (rectNew != wpl.rcNormalPosition) ) { VERIFY( ::SetWindowPos(hwnd,HWND_TOP, rectNew.left,rectNew.top,rectNew.Width(),rectNew.Height(), SWP_NOACTIVATE|SWP_NOOWNERZORDER|SWP_NOZORDER) ); } } catch(...) { delete pli; throw; } } delete pli; return true;}//////////////////////////////////////////////////////////////////////// main layout engine///////////////////////////////////////////////////////////////////////* * Layout() * -------- * Iterates through all child windows and calls DoMoveCtrl() for them. * This function is NOT virtual. * To implement your own layout algorithm, please * a) overwrite DoCreateLayoutInfo() to return an object of a class * derived from cdxCDynamicLayoutInfo. * You can put any user-data into your object; it will be passed * on to the DoMoveCtrl() function. * b) overwrite DoMoveCtrl() and implement the layout logic. * An example can be found in the example project, anytime. */void cdxCDynamicWnd::Layout(){ if(!IsWindow()) { ASSERT(IsWindow()); return; } // resize stuff cdxCDynamicLayoutInfo *pli = DoCreateLayoutInfo(); if(!pli) { ASSERT(false); // YOU MUST PROVIDE A LAYOUT INFO BLOCK ! return; } try { HDWP hdwp = ::BeginDeferWindowPos(pli->m_nCtrlCnt); HWND hwnd; bool bRepeat; CRect rectNew; UINT id; WINDOWPLACEMENT wpl; DWORD swpFlags = SWP_NOACTIVATE|SWP_NOOWNERZORDER|SWP_NOZORDER|(!(m_nFlags & flSWPCopyBits) ? SWP_NOCOPYBITS : 0); if(!( hwnd = ::GetWindow(m_pWnd->m_hWnd,GW_CHILD) )) { TRACE(_T("*** NOTE[cdxCDynamicWnd::Layout()]: The window at 0x%lx does not have child windows.\n"),(DWORD)m_pWnd->m_hWnd); return; } do { bRepeat = false; for(; hwnd; hwnd = ::GetNextWindow(hwnd,GW_HWNDNEXT)) { wpl.length = sizeof(WINDOWPLACEMENT); if(!::GetWindowPlacement(hwnd,&wpl)) { ASSERT(false); // GetWindowPlacement() failed continue; } rectNew = wpl.rcNormalPosition; ASSERT(rectNew.left >= 0); id = ::GetDlgCtrlID(hwnd); if(!DoMoveCtrl(hwnd,id,rectNew,*pli) || (rectNew == wpl.rcNormalPosition) ) { // window doesn't need to be moved // (position is not been changed) continue; } if(hdwp) { if(!( hdwp = ::DeferWindowPos(hdwp,hwnd,HWND_TOP, rectNew.left,rectNew.top,rectNew.Width(),rectNew.Height(), swpFlags) )) { TRACE(_T("*** ERROR[cdxCDynamicWnd::ReorganizeControls()]: DeferWindowPos() failed ??\n")); bRepeat = true; break; // error; we'll repeat the loop by using SetWind騱Pos() // this won't look good, but work :) } } else { VERIFY( ::SetWindowPos(hwnd,HWND_TOP, rectNew.left,rectNew.top,rectNew.Width(),rectNew.Height(), swpFlags) ); } } } while(bRepeat); if(hdwp) { VERIFY( ::EndDeferWindowPos(hdwp) ); } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -