|
Hi Mizan,
I have re-sent the demo project through following mail id vishnu1989@outlook.com.
Hope you receive it.
Regards,
Ankita
|
|
|
|
|
I received your mail and I saw your code.
You have not assigned a proper ID for the placeholder control. The ID you are using is IDC_STATIC. It is a default ID that has value -1. which is good for nothing. What you need is assign a proper ID to the place holder control (i.e., IDC_STATIC_PLACEHOLDER).
And you will not need a second CWndResizer in your case, at for resizing the place holder control. But if you place other controls in the placeholder control and you want to resize those, then you will need another CWndResizer.
/Mizan
|
|
|
|
|
Hi Mizan,
Thanks for your suggestion. As per your suggestion we have removed the second re-sizer and after hooking the dialog with the window re-sizer, we anchored the controls, i.e. Tab Control, Place holder and dynamically created dialog.
If we are not anchoring the dialog created at runtime, then only tab control and place holder are re-sizing, while dialog created at runtime still remains at its original location.
If we are anchoring the dialog created at runtime too, then it returns 0 and program terminates at ASSERT(ok)
Following is our modified code.
Hierarchy of controls is
Main Dialog --> Tab Control is placed within the main dialog --> Place Holder is within the Tab Control --> Dialog is placed within the Place Holder (This dialog is created at runtime).
BOOL ok = FALSE;
// hook main dialog with first object of re-sizer
ok = resizer.Hook(this);
ASSERT(ok);
//anchor tab control with re-sizer
ok = resizer.SetAnchor(m_PRCTab.GetDlgCtrlID(),ANCHOR_ALL);
ASSERT(ok);
//anchor place holder with re-sizer
ok = resizer.SetAnchor(IDC_STATIC_PlaceHolder,ANCHOR_ALL);
ASSERT(ok);
//anchor dynamically created dialog with re-sizer
ok = resizer.SetAnchor(IDD_DIALOG_First,ANCHOR_ALL);
ASSERT(ok);
<b>After trying this we used second re-sizer too as shown in code below</b>
BOOL ok = FALSE;
// hook main dialog with first object of re-sizer
ok = resizer.Hook(this);
ASSERT(ok);
//anchor tab control with re-sizer
ok = resizer.SetAnchor(m_PRCTab.GetDlgCtrlID(),ANCHOR_ALL);
ASSERT(ok);
//anchor place holder with re-sizer
ok = resizer.SetAnchor(IDC_STATIC_PlaceHolder,ANCHOR_ALL);
ASSERT(ok);
// hook place holder with second object of re-sizer
ok = resizer2.Hook(GetDlgItem(IDC_STATIC_PlaceHolder));
ASSERT(ok);
//anchor dynamically created dialog with second object of re-sizer
ok = resizer2.SetAnchor(IDD_DIALOG_First,ANCHOR_ALL);
ASSERT(ok);
<b>In this case too after anchoring the dialog created at runtime with second object of resizer, it returns 0 and program terminates at ASSERT(ok)</b>
It would be very kind of you, If you can modify the demo project (sent at ur yahoo mail id) to make it workable, so that we can refer the same.
Regards,
Ankita
|
|
|
|
|
I'm sorry, but I cannot help you in your detail implementation any further. I simply don't have time of it. I suggest you look at the implementation of the Example 8 and Example 9 of the source code of this article.
Regards
Mizan
|
|
|
|
|
The CTabCtrl does not resize the child dialog automaticly, but the CPropertySheet does.
So, you have to notify the child dialog to resize its size manually.
---------------------------------------------------------------
Here a class (CMTabCtrl) may help you.
The CMTabCtrl class is adpoted from CSTabCtrl class that hosted in this site.
[^]
class CMTabCtrl : public CTabCtrl
{
public:
CMTabCtrl();
~CMTabCtrl();
public:
public:
virtual BOOL AttachDialogToTab(CDialog * _pDialog, INT _nTabNum);
virtual int SetCurSel( int nItem );
protected:
afx_msg BOOL OnSelchange(NMHDR* pNMHDR, LRESULT* pResult);
afx_msg void OnDestroy();
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
afx_msg void OnSize(UINT nType, int cx, int cy);
DECLARE_MESSAGE_MAP()
private:
class CPageToControlsMap : public CMap <INT, INT&, CDialog*, CDialog*&>
{
public:
CPageToControlsMap( );
~CPageToControlsMap( );
BOOL AttachDialog(INT _nTabNum,CDialog* _pDialog);
BOOL ShowWindows ( INT _nCurrPage, INT _nCmdShow );
void ResizePages(LPRECT rect);
};
INT m_nPrevSel;
CPageToControlsMap m_TabPagesMap;
};
#endif // INC_MTABCTRL
#include "stdafx.h"
#include "MTabCtrl.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
CMTabCtrl::CPageToControlsMap::CPageToControlsMap( )
{
}
CMTabCtrl::CPageToControlsMap::~CPageToControlsMap( )
{
CPageToControlsMap::RemoveAll();
}
BOOL CMTabCtrl::CPageToControlsMap::AttachDialog(INT _nTabNum, CDialog* _pDialog)
{
SetAt(_nTabNum, _pDialog);
::ShowWindow( _pDialog->GetSafeHwnd(), SW_HIDE );
return TRUE;
}
BOOL CMTabCtrl::CPageToControlsMap::ShowWindows ( INT _nCurrPage, INT _nCmdShow )
{
CList <CWnd *, CWnd *> * _pCtrlList = NULL;
CDialog* _pDialog = NULL;
if(Lookup(_nCurrPage, _pDialog) && _pDialog)
return _pDialog -> ShowWindow ( _nCmdShow );
else
return FALSE;
}
void CMTabCtrl::CPageToControlsMap::ResizePages(LPRECT rect)
{
POSITION pos = GetStartPosition();
while (pos)
{
INT nPage;
CDialog* pDialog;
GetNextAssoc(pos, nPage, pDialog);
pDialog->MoveWindow(rect);
}
}
CMTabCtrl::CMTabCtrl()
{
m_nPrevSel = -1;
}
CMTabCtrl::~CMTabCtrl()
{
}
BEGIN_MESSAGE_MAP(CMTabCtrl, CTabCtrl)
ON_NOTIFY_REFLECT_EX(TCN_SELCHANGE, OnSelchange)
ON_WM_DESTROY()
ON_WM_CREATE()
ON_WM_SIZE()
END_MESSAGE_MAP()
int CMTabCtrl::SetCurSel( int nItem )
{
int _nRetVal = CTabCtrl::SetCurSel(nItem);
NMHDR _nDummyNMHDR;
LRESULT _nDummyLRESULT;
OnSelchange(&_nDummyNMHDR,&_nDummyLRESULT);
return _nRetVal;
}
BOOL CMTabCtrl::AttachDialogToTab(CDialog * _pDialog,
INT _nTabNum)
{
if(_nTabNum >= GetItemCount())
{
ASSERT(FALSE);
return FALSE;
}
m_TabPagesMap.AttachDialog (_nTabNum, _pDialog);
return TRUE;
}
BOOL CMTabCtrl::OnSelchange(NMHDR* pNMHDR, LRESULT* pResult)
{
INT _nCurrSel = GetCurSel();
m_TabPagesMap.ShowWindows (m_nPrevSel, SW_HIDE);
m_TabPagesMap.ShowWindows (_nCurrSel, SW_SHOW);
m_nPrevSel = _nCurrSel;
*pResult = 0;
return FALSE;
}
int CMTabCtrl::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
m_nPrevSel = -1;
return CTabCtrl::OnCreate(lpCreateStruct);
}
void CMTabCtrl::OnDestroy()
{
CTabCtrl::OnDestroy();
m_TabPagesMap.RemoveAll();
}
void CMTabCtrl::OnSize(UINT nType, int cx, int cy)
{
RECT rect;
GetWindowRect(&rect);
AdjustRect(FALSE, &rect);
CWnd* pParent = GetParent();
if (pParent)
{
pParent->ScreenToClient(&rect);
m_TabPagesMap.ResizePages(&rect);
}
}
|
|
|
|
|
Hi,
I'm looking at your code.
What I have noticed is that you missed to declare virtual all destructors from your CPanel's derived classes. This isn't a big issue in your implementation as long as you don't allocate memory inside a CPanel's derived classes and you would need to deallocate it on a destructor call and indeed it seems so, at least from a first sight. However, there is at least a case in your code where it is 'useful':
CGripperPanel relies on its destructor to properly close the theme and this destructor won't be called when the virtual CPanel's destructor will cycle on its children (and so on ) deleting them.
Did you get it?
Let me know if it's unclear, thanks.
UPDATE: I've test it in debug mode and the destructor of CGripperPanel is called when you delete it, as CPanel *, in the ::Unhook function. From my knowledge it shouldn't have worked in that way, but probably someone else has a good explanation about that.
UPDATE/2: sorry, discard the above comment. I was thinking to something else.
|
|
|
|
|
Hi,
I was looking for a solution about flickering during resizing of windows and I came to your example.
I've downloaded your exe only and I admit it is a nice job.
However, when you resize your windows you can see a lot of flickering on children controls.
If you resize the right edge then the flickering is minor but visible, if you resize the left edge you see a lot of flickering.
If you go down with win32 stuff as I did (just to avoid some mfc runtime overhead)
and try to resize a dialog for example, with children specified in particular positions, you will see a lot of flickering. I've almost eliminated the filckering when I resize on the right edge but not on the left edge.
You can see this problem on your example too. It seems to me there is an underlying "problem" with the left resizing.
Is there any way to eliminate this?
|
|
|
|
|
|
Hi, I'm testing this control its excellent and works perfectly.
However I need to use a picture control with a fixed width and height proportions, lets say 4:3 for showing a photo, and keeping these proportions when resizing, and I cannot find a way to do this.
can it be done? thanks
|
|
|
|
|
No, aspect ratio is not supported. Sorry.
/Mizan
|
|
|
|
|
thanks for the response, I will try to add it to the class, lets see..
|
|
|
|
|
Hello,
First of all, great work on this. I have an issue though, my application follows the MDI format where there are a given number of child windows (always the same), these child windows have controls in them, some have only one control and others have more. I can resize these child windows manually (with the mouse for example) without any problem, but as soon as I do a Tile or Cascade and the resulting size requires (either horizontal or vertical) scrollbars then the controls inside the child window compress (see image link). Clicking on the scroll bar fixes this issue.
I traced the problem to the GetTrueClientRect() function, the nMin and nMax scroll ranges are always 0-100 respectively after an MDITile, MDICascade or ::SetWindowPos. I found out the issue is also on ::SetWindowPos when I build my own variation of MDITile and the same issue persisted.
Also, Microsoft recommends to use GetScrollInfo instead of the individual scroll functions, you have:
pWnd->GetScrollRange(SB_VERT, &nMin, &nMax);
nCur = pWnd->GetScrollPos(SB_VERT);
which I changed to:
SCROLLINFO ScrollInfo;
ScrollInfo.cbSize = sizeof(SCROLLINFO);
ScrollInfo.fMask = SIF_RANGE | SIF_POS;
pWnd->GetScrollInfo(SB_VERT, &ScrollInfo);
nMin = ScrollInfo.nMin;
nMax = ScrollInfo.nMax;
nCur = ScrollInfo.nPos;
However the problem I previously mentioned still persists.
http://img10.imageshack.us/img10/9025/zbtilehorizerror.png[^]
Edit: The child views are CFormView based, compiler is VS2010 32bit and OS is Windows 7 Enterprise x64
modified 27-Jul-12 5:05am.
|
|
|
|
|
Is the child window a CFormView?
Which overloaded of the Hook method did you use?
Best regards,
Mizan
|
|
|
|
|
I used
BOOL CWndResizer::Hook(CWnd * pParent, CSize & size)
where size is set on OnCreate() as per your demo. Yes, the childs are based off CFormView
|
|
|
|
|
You must to init...
call CFormView==>SetScrollSizes and then call m_resizer.SetMinimumSize.
Hi?
|
|
|
|
|
When I iinclude WndResizer.cpp and WndResizer.h in my VC2003 project, I can't compile it.
How can I use it in VC2003 project?
|
|
|
|
|
You have to be more specific about the errors you get for me to tell what the problem is. Try posting the errors. what is your operating system ?
BR
Mizan
|
|
|
|
|
Hi all
Is it possible to add support for dynamically hiding and showing controls with automatic layout of other visible controls?
Or how can it be done with existing version od CWndResizer?
PS Great piece of software, I like the idea and implementation simplicity of CWNdResizer
Greets, Michał
|
|
|
|
|
I am glade you like this class.
As far as "hiding/showing", I really didn't understand what you are trying to achieve. If you can eleborate what you are trying to do then may be I can have some thoughts on that.
/Mizan
|
|
|
|
|
Suppose we have a dialog window with few controls.
It could be convenient to add few controls from dialog to some panel and selectively hide this panel. Other controls on dialog should reposition/resize itself to accommodate space or dialog should shrink itself. Of course this should work opposite way - showing hidden panel should cause other controls shrink or dialog itself make bigger.
I think idea is shown on pictures below:
Dialog when panel with icon and details is hidden:
_______________________________________________________
| - O x |
| ___________________________________________________ |
| |---------------------------------------------------| |
| | List element 1 (selected) | |
| |---------------------------------------------------| |
| | List element 2 | |
| |---------------------------------------------------| |
| | ... | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| |___________________________________________________| |
| __________ __________ |
| | || | |
| [ ] Show details | OK || Cancel | |
| |__________||__________| |
|_______________________________________________________|
Dialog when panel with icon and details is visible:
_______________________________________________________
| - O x |
| ___________________________________________________ |
| |---------------------------------------------------| |
| | List element 1 (selected) | |
| |---------------------------------------------------| |
| | List element 2 | |
| |---------------------------------------------------| |
| | ... | |
| | | |
| | | |
| |___________________________________________________| |
| |
| ..... Some details about element 1 |
| ******* |
| OOOOOOO This panel should be set visible and list |
| :*****: above shoud shrink to leave room for |
| details panel |
| __________ __________ |
| | || | |
| [X] Show details | OK || Cancel | |
| |__________||__________| |
|_______________________________________________________|
These panels can be more than one in dialog, hiding any of them and showing another can be used for switching interface.
The result above can be achieved by using Split Container Panel (after some tweaking, because you can't set minimum size of panel in splitter to (0,0), due to small bug), but much more convenient would be considering visibility of panel in layout computations (hidden panels should be simply omitted).
Greetings, Michał
|
|
|
|
|
Hi, thank you for the explantion. if I understand it correctly now, then I would say you trying to do something like this: Full-featured XP Style Collapsible Panel[^]
Currently there is no support for this in CWndResizer. One may tweak the CSplitContaner class to make somehting close to a "collapsible Panel" or one may also create new class to do this.
I have a new design in mind, but I just don't have the time to implement that yet. But I do think this "collapsible panel" would be very usful feature of CWndResizer. if anyone does goahead and implenment this feature I would be glade to include that in this article.
BTW you did an excelent job in sketching the layout
Regards,
Mizan
|
|
|
|
|
Well, I managed to tweak your code to support what I wanted to, but I'm not sure it is as elegant as I wanted. But it works.
First I needed to add property 'Visibility'. It is already in panels which inherit from CVisualPanel , but it is needed also in CUIPanel (for hiding controls). To achieve this, I added two virtual functions in CPanel : SetVisible() and GetVisible() , and reimplemented them in CUIPanel and moved m_bVisible variable from CVisualPanel to CPanel itself. I think it could be convenient for other layouts.
CPanel::SetVisible() shows/hides also child panels.
Changes to CPanel
BOOL CPanel::SetVisible(BOOL bVisible)
{
m_bVisible = bVisible;
POSITION pos = Children.GetHeadPosition();
while( pos )
{
CPanel *pPanel = Children.GetNext( pos );
pPanel->SetVisible( bVisible );
}
return TRUE;
}
BOOL CPanel::GetVisible(BOOL &bVisible)
{
bVisible = m_bVisible;
return TRUE;
}
Changes to CUIPanel
BOOL CUIPanel::SetVisible(BOOL bVisible)
{
BOOL bRes = FALSE;
CPanel::SetVisible( bVisible );
CWnd *wnd = GetHookedWnd();
if( wnd )
{
CWnd *ctl = wnd->GetDlgItem( m_uID );
if( ctl )
bRes = ctl->ShowWindow( bVisible ? SW_SHOW : SW_HIDE );
}
return bRes;
}
BOOL CUIPanel::GetVisible(BOOL &bVisible)
{
bVisible = m_bVisible;
return TRUE;
}
Second I removed class CSplitPanel (which was unnecessary and caused problems with finding nested CSplitContainers ) - replaced with normal CPanel .
Changes in CSplitContainer::Create()
CSplitContainer * CSplitContainer::Create(CPanel * pPanelA, CPanel * pPanelB)
{
CRect rcDest(0, 0, 0, 0);
CWndResizer::SplitterOrientation orien = CWndResizer::SPLIT_CONTAINER_H;
if (::IntersectRect(&rcDest, pPanelA, pPanelB) == TRUE)
{
return NULL;
}
if (pPanelA->right < pPanelB->left)
{
orien = CWndResizer::SPLIT_CONTAINER_H;
}
else if (pPanelA->bottom < pPanelB->top)
{
orien = CWndResizer::SPLIT_CONTAINER_V;
}
else
{
return NULL;
}
CSplitContainer * pSpliter = new CSplitContainer(pPanelA, pPanelB, orien);
return pSpliter;
}
Third - I added two more "special" values for SetFixedPanel() function - FIXED_PANEL_TOPLEFT_HIDDEN and FIXED_PANEL_BOTTOMRIGHT_HIDDEN , which have special meaning of hiding top(left) or bottom(right) control in CSplitContainer and also hides CSplitterPanel .
Former special values I named FIXED_PANEL_TOPLEFT (=1) and PANEL_BOTTOMRIGHT (=2)
Changes to CSplitContainer::OnResized()
class CWndResizer
{
enum FixedPanel
{
FIXED_NONE = 0,
FIXED_TOPLEFT = 1,
FIXED_BOTTOMRIGHT = 2,
FIXED_TOPLEFT_HIDDEN = 3,
FIXED_BOTTOMRIGHT_HIDDEN = 4,
FIXED_LEFT = FIXED_TOPLEFT,
FIXED_TOP = FIXED_TOPLEFT,
FIXED_RIGHT = FIXED_BOTTOMRIGHT,
FIXED_BOTTOM = FIXED_BOTTOMRIGHT,
FIXED_LEFT_HIDDEN = FIXED_TOPLEFT_HIDDEN,
FIXED_TOP_HIDDEN = FIXED_TOPLEFT_HIDDEN,
FIXED_RIGHT_HIDDEN = FIXED_BOTTOMRIGHT_HIDDEN,
FIXED_BOTTOM_HIDDEN = FIXED_BOTTOMRIGHT_HIDDEN,
};
};
void CSplitContainer::OnResized()
{
CPanel::OnResized();
BOOL bShowA = TRUE;
BOOL bShowB = TRUE;
BOOL bShowS = TRUE;
if (m_Orientation == CWndResizer::SPLIT_CONTAINER_H)
{
if (Width() < MinSize.cx)
return;
if (m_FixedPanel == CWndResizer::FIXED_LEFT ) {
m_pPanelB->left = m_pPanelA->right + m_nSplitterSize;
if (m_pPanelB->MinSize.cx > m_pPanelB->Width() )
{
m_pPanelB->left = m_pPanelB->right - m_pPanelB->MinSize.cx;
m_pPanelA->right = m_pPanelB->left - m_nSplitterSize;
}
}
else if (m_FixedPanel == CWndResizer::FIXED_RIGHT ) {
m_pPanelA->right = m_pPanelB->left - m_nSplitterSize;
if (m_pPanelA->MinSize.cx > m_pPanelA->Width() )
{
m_pPanelA->right = m_pPanelA->left + m_pPanelA->MinSize.cx;
m_pPanelB->left = m_pPanelA->right + m_nSplitterSize;
}
}
else if (m_FixedPanel == CWndResizer::FIXED_LEFT_HIDDEN ) {
m_pPanelB->left = m_pPanelA->left;
m_pPanelA->right = m_pPanelA->left;
bShowS = FALSE;
}
else if (m_FixedPanel == CWndResizer::FIXED_RIGHT_HIDDEN ) {
m_pPanelA->right = m_pPanelB->right;
m_pPanelB->left = m_pPanelB->right;
bShowS = FALSE;
}
else
{
m_pPanelA->right = (LONG) ((double)m_pPanelA->left + ((double)this->Width() * m_nRatio));
if (m_pPanelA->MinSize.cx > m_pPanelA->Width() )
{
m_pPanelA->right = m_pPanelA->left + m_pPanelA->MinSize.cx;
}
m_pPanelB->left = m_pPanelA->right + m_nSplitterSize;
if (m_pPanelB->MinSize.cx > m_pPanelB->Width() )
{
m_pPanelB->left = m_pPanelB->right - m_pPanelB->MinSize.cx;
m_pPanelA->right = m_pPanelB->left - m_nSplitterSize;
}
}
if (m_pPanelA->Width() <= 2)
bShowA = FALSE;
if (m_pPanelB->Width() <= 2)
bShowB = FALSE;
}
else
{
if (Height() < MinSize.cy)
{
return;
}
if (m_FixedPanel == CWndResizer::FIXED_TOP ) {
m_pPanelB->top = m_pPanelA->bottom + m_nSplitterSize;
if (m_pPanelB->MinSize.cy > m_pPanelB->Height() )
{
m_pPanelB->top = m_pPanelB->bottom - m_pPanelB->MinSize.cy;
m_pPanelA->bottom = m_pPanelB->top - m_nSplitterSize;
}
}
else if (m_FixedPanel == CWndResizer::FIXED_BOTTOM ) {
m_pPanelA->bottom = m_pPanelB->top - m_nSplitterSize;
if (m_pPanelA->MinSize.cy > m_pPanelA->Height() )
{
m_pPanelA->bottom = m_pPanelA->top + m_pPanelA->MinSize.cy;
m_pPanelB->top = m_pPanelA->bottom + m_nSplitterSize;
}
}
else if (m_FixedPanel == CWndResizer::FIXED_TOP_HIDDEN ) {
m_pPanelB->top = m_pPanelA->top;
bShowA = FALSE;
bShowS = FALSE;
}
else if (m_FixedPanel == CWndResizer::FIXED_BOTTOM_HIDDEN ) {
m_pPanelA->bottom = m_pPanelB->bottom;
bShowS = FALSE;
bShowB = FALSE;
}
else
{
m_pPanelA->bottom = (LONG) ((double)m_pPanelA->top + ((double)this->Height() * m_nRatio));
if (m_pPanelA->MinSize.cy > m_pPanelA->Height() )
{
m_pPanelA->bottom = m_pPanelA->top + m_pPanelA->MinSize.cy;
}
m_pPanelB->top = m_pPanelA->bottom + m_nSplitterSize;
if (m_pPanelB->MinSize.cy > m_pPanelB->Height() )
{
m_pPanelB->top = m_pPanelB->bottom - m_pPanelB->MinSize.cy;
m_pPanelA->bottom = m_pPanelB->top - m_nSplitterSize;
}
}
if (m_pPanelA->Height() <= 2)
bShowA = FALSE;
if (m_pPanelB->Height() <= 2)
bShowB = FALSE;
}
m_pPanelA->SetVisible( bShowA );
if( bShowA )
m_pPanelA->OnResized();
m_pPanelB->SetVisible( bShowB );
if( bShowB )
m_pPanelB->OnResized();
if( bShowS )
{
if( !bShowA )
m_nRatio = 0;
else if( !bShowB )
m_nRatio = 100;
GetSplitArea(m_pSplitter);
m_pSplitter->SetVisible( !m_IsSplitterFixed );
m_pSplitter->OnResized();
}
else
m_pSplitter->SetVisible( FALSE );
}
I also added support to use resize gripper (for whole dialog) to resizing
Changes to support grip to resize dialog
class CWndResizer
{
enum ResizeGrip
{
RESIZE_GRIP_HIDDEN = 0,
RESIZE_GRIP_VISIBLE = 1,
RESIZE_GRIP_VISIBLE_ACTIVE_RECT = 2,
RESIZE_GRIP_VISIBLE_ACTIVE_TRIANGLE = 2
};
};
I added to CWndResizer::WindowProc() :
case WM_NCHITTEST:
lResult = pResizer->OnNcHitTest( CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)) );
if( lResult != HTNOWHERE )
return lResult;
break;
And added function CWndResizer::OnNcHitTest()
LRESULT CWndResizer::OnNcHitTest( CPoint point )
{
CGripperPanel * pPanel = (CGripperPanel *)FindPanelByName(&root, ResizeGripperPanelName);
if( !pPanel || !pPanel->m_bVisible )
return HTNOWHERE;
ASSERT( m_pHookedWnd != NULL );
m_pHookedWnd->ScreenToClient( &point );
if( pPanel->m_bVisible == RESIZE_GRIP_VISIBLE_ACTIVE_TRIANGLE )
{
if( pPanel->PtInTriangle(point) )
return HTBOTTOMRIGHT;
}
else if( pPanel->m_bVisible == RESIZE_GRIP_VISIBLE_ACTIVE_RECT )
{
if( pPanel->PtInRect( point ) )
return HTBOTTOMRIGHT;
}
return HTNOWHERE;
}
And also these functions in CPanel :
BOOL CPanel::PtInTriangle( CPoint point, UINT nEdge ) const
{
switch( nEdge )
{
case ANCHOR_TOPLEFT:
return PtInTriangle( point, CPoint(left,top), CPoint(right,top), CPoint(left,bottom) );
case ANCHOR_TOPRIGHT:
return PtInTriangle( point, CPoint(left,top), CPoint(right,top), CPoint(right,bottom) );
case ANCHOR_BOTTOMLEFT:
return PtInTriangle( point, CPoint(left,top), CPoint(left,bottom), CPoint(right,bottom) );
case ANCHOR_BOTTOMRIGHT:
return PtInTriangle( point, CPoint(left,bottom), CPoint(right,top), CPoint(right,bottom) );
default:
return FALSE;
}
}
static int GetSign( const CPoint &a, const CPoint &b, const CPoint &c )
{
return (a.x - c.x) * (b.y - c.y) - (b.x - c.x) * (a.y - c.y);
}
BOOL CPanel::PtInTriangle( CPoint point, CPoint v1, CPoint v2, CPoint v3 )
{
bool b1 = GetSign(point, v1, v2) < 0;
bool b2 = GetSign(point, v2, v3) < 0;
bool b3 = GetSign(point, v3, v1) < 0;
return ((b1 == b2) && (b2 == b3));
}
I also reorganized code (as in git repository by Igor Okulist), MFC/C++ Helper Class for Window Resizing[^]:
Moved most of the CPanel -derived classes definitions to cpp file, moved CPanel definition to outside of CWndResizer class.
I also added of course test dialog (similar to one described in prevoius post (you liked much ) to test application.
If you want, I can post all my changes as zip file, but I don't know where to put zipfile. This was the reason to draw previous dialogs with ASCII-art
Greetings
Michał
modified 4-Jun-12 10:09am.
|
|
|
|
|
Hello,
I tried to implement your modification but didn't succeed.
Could you send me the modified projet and the test dialog class.
Thank you
Remarks : from explanation I notes the following errors :
LRESULT CWndResizer::OnNcHitTest( CPoint point )
{
CGripperPanel * pPanel = (CGripperPanel *)FindPanelByName(&root, ResizeGripperPanelName);
...
if( pPanel->PtInTriangle(point) )
return HTBOTTOMRIGHT;
...
}
BOOL CPanel::PtInTriangle( CPoint point, UINT nEdge ) const
{
switch( nEdge )
{
case ANCHOR_TOPLEFT:
...
case ANCHOR_TOPRIGHT:
...
case ANCHOR_BOTTOMLEFT:
...
case ANCHOR_BOTTOMRIGHT:
...
}
}
MaxMax14
|
|
|
|
|
Sorry, I didn't notice question. I hardly had time for looking to codeproject
If you still need this info:
CPanel::PtInTriangle() has default second argument set to ANCHOR_BOTTOMRIGHT:
CPanel::PtInTriangle( CPoint point, UINT nEdge = ANCHOR_BOTTOMRIGHT) const;
and ResizeGripperPanelName was defined as used before but declared as public static member, along with RootPanelName.
class WndResizer
{
public:
static const TCHAR ResizeGripperPanelName[];
static const TCHAR RootPanelName[];
...
};
and in WndResizer.cpp:
const TCHAR CWndResizer::ResizeGripperPanelName[] = _T("_resizeGrip");
const TCHAR CWndResizer::RootPanelName[] = _T("_root");
and below is full implementation i case someone will need it.
WndResizer.h
#pragma once
#define ANCHOR_LEFT 1
#define ANCHOR_TOP 2
#define ANCHOR_RIGHT 4
#define ANCHOR_BOTTOM 8
#define ANCHOR_HORIZONTALLY_CENTERED 16
#define ANCHOR_VERTICALLY_CENTERED 32
#define ANCHOR_PRIORITY_RIGHT 64 // by defualt, left has higher priority
#define ANCHOR_PRIORITY_BOTTOM 128 // by defualt, top has higher priority
#define ANCHOR_IGNORE 256 // if set, panel is ignored in layout computations
#define ANCHOR_TOPLEFT (ANCHOR_LEFT | ANCHOR_TOP)
#define ANCHOR_TOPRIGHT (ANCHOR_RIGHT | ANCHOR_TOP)
#define ANCHOR_BOTTOMLEFT (ANCHOR_LEFT | ANCHOR_BOTTOM)
#define ANCHOR_BOTTOMRIGHT (ANCHOR_RIGHT | ANCHOR_BOTTOM)
#define ANCHOR_VERTICALLY (ANCHOR_TOP | ANCHOR_BOTTOM)
#define ANCHOR_HORIZONTALLY (ANCHOR_LEFT | ANCHOR_RIGHT)
#define ANCHOR_ALL (ANCHOR_VERTICALLY | ANCHOR_HORIZONTALLY)
#define DOCK_NONE 0
#define DOCK_LEFT 1
#define DOCK_TOP 2
#define DOCK_RIGHT 3
#define DOCK_BOTTOM 4
#define DOCK_FILL 5
class CPanel;
class CUIPanel;
typedef CList<CPanel *, CPanel *> CPanelList;
class CPanel : public CRect
{
public:
CPanel();
CPanel(const CRect * prc);
virtual ~CPanel();
UINT Anchor;
UINT Dock;
CString Name;
CPanel * Parent;
CPanelList Children;
int LeftOffset;
int TopOffset;
int RightOffset;
int BottomOffset;
CSize MinSize;
CSize MaxSize;
BOOL m_bVisible;
virtual void OnResized();
virtual BOOL AddChild(CPanel * prc);
virtual BOOL RemoveChild(CPanel * prc);
virtual BOOL SetAnchor(UINT anchor);
virtual BOOL SetMinSize(CSize & size);
virtual BOOL SetMaxSize(CSize & size);
virtual BOOL SetOffset(UINT anchor, int offset);
virtual BOOL SetVisible(BOOL bVisible);
virtual BOOL GetVisible(BOOL &bVisible);
virtual BOOL IsVisible();
virtual CString ToString();
virtual CString GetTypeName();
virtual CWnd * GetHookedWnd();
BOOL PtInTriangle( CPoint point, UINT nEdge = ANCHOR_BOTTOMRIGHT ) const;
static BOOL PtInTriangle( CPoint point, CPoint v1, CPoint v2, CPoint v3 );
private:
void Init();
};
class CRootPanel : public CPanel
{
public:
CRootPanel();
~CRootPanel();
virtual CWnd * GetHookedWnd();
CWnd * m_pHookWnd;
virtual CString GetTypeName();
};
class CWndResizer
{
public:
static const TCHAR ResizeGripperPanelName[];
static const TCHAR RootPanelName[];
enum SplitterOrientation
{
SPLIT_CONTAINER_H = 1,
SPLIT_CONTAINER_V = 2,
};
enum FlowDirection
{
LEFT_TO_RIGHT = 3,
TOP_TO_BOTTOM = 4,
};
enum FixedPanel
{
FIXED_NONE = 0,
FIXED_TOPLEFT = 1,
FIXED_BOTTOMRIGHT = 2,
FIXED_TOPLEFT_HIDDEN = 3,
FIXED_BOTTOMRIGHT_HIDDEN = 4,
FIXED_LEFT = FIXED_TOPLEFT,
FIXED_TOP = FIXED_TOPLEFT,
FIXED_RIGHT = FIXED_BOTTOMRIGHT,
FIXED_BOTTOM = FIXED_BOTTOMRIGHT,
FIXED_LEFT_HIDDEN = FIXED_TOPLEFT_HIDDEN,
FIXED_TOP_HIDDEN = FIXED_TOPLEFT_HIDDEN,
FIXED_RIGHT_HIDDEN = FIXED_BOTTOMRIGHT_HIDDEN,
FIXED_BOTTOM_HIDDEN = FIXED_BOTTOMRIGHT_HIDDEN,
};
enum ResizeGrip
{
RESIZE_GRIP_HIDDEN = 0,
RESIZE_GRIP_VISIBLE = 1,
RESIZE_GRIP_VISIBLE_ACTIVE_RECT = 2,
RESIZE_GRIP_VISIBLE_ACTIVE_TRIANGLE = 2
};
public:
CWndResizer(void);
~CWndResizer(void);
BOOL Hook(CWnd * pWnd);
BOOL Hook(CWnd * pWnd, CSize & size);
BOOL Unhook();
BOOL CreatePanel(UINT uID);
BOOL CreatePanel(LPCTSTR panelName, const CUIntArray * parrID, BOOL setAsChildren = FALSE);
BOOL CreatePanel(LPCTSTR panelName, const UINT * parrID, BOOL setAsChildren = FALSE);
BOOL CreatePanel(LPCTSTR panelName, const CRect * prcPanel);
BOOL CreateSplitContainer(LPCTSTR splitContainerName, LPCTSTR panelNameA, LPCTSTR panelNameB);
BOOL CreateSplitContainer(LPCTSTR splitContainerName, LPCTSTR panelNameA, UINT panelIDB);
BOOL CreateSplitContainer(LPCTSTR splitContainerName, UINT panelIDA, UINT panelIDB);
BOOL CreateSplitContainer(LPCTSTR splitContainerName, UINT panelIDA, LPCTSTR panelNameB);
BOOL CreateFlowLayoutPanel(LPCTSTR panelName, const CUIntArray * parrID, BOOL setAsChildren = FALSE);
BOOL CreateFlowLayoutPanel(LPCTSTR panelName, const UINT * parrID, BOOL setAsChildren = FALSE);
BOOL CreateFlowLayoutPanel(LPCTSTR panelName, const CRect * prcPanel);
BOOL SetAnchor(LPCTSTR panelName, UINT anchor);
BOOL SetAnchor(UINT panelID, UINT anchor);
BOOL GetAnchor(LPCTSTR panelName, UINT & anchor);
BOOL GetAnchor(UINT panelID, UINT & anchor);
BOOL SetOffset(LPCTSTR panelName, UINT anchor, int offset);
BOOL SetOffset(UINT panelID, UINT anchor, int offset);
BOOL SetDock(LPCTSTR panelName, UINT anchor);
BOOL SetDock(UINT panelID, UINT anchor);
BOOL GetDock(LPCTSTR panelName, UINT & anchor);
BOOL GetDock(UINT panelID, UINT & anchor);
BOOL SetParent(LPCTSTR panelName, LPCTSTR parentName);
BOOL SetParent(UINT panelID, LPCTSTR parentName);
BOOL SetParent(LPCTSTR panelName, UINT parentID);
BOOL SetParent(UINT panelID, UINT parentID);
BOOL GetParent(LPCTSTR panelName, CString & parentName);
BOOL GetParent(UINT panelID, CString & parentName);
BOOL SetMinimumSize(LPCTSTR panelName, CSize & size);
BOOL SetMinimumSize(UINT panelID, CSize & size);
BOOL GetMinimumSize(LPCTSTR panelName, CSize & size) ;
BOOL GetMinimumSize(UINT panelID, CSize & size) ;
BOOL SetMaximumSize(LPCTSTR panelName, CSize & size);
BOOL SetMaximumSize(UINT panelID, CSize & size);
BOOL GetMaximumSize(LPCTSTR panelName, CSize & size) ;
BOOL GetMaximumSize(UINT panelID, CSize & size) ;
BOOL SetFixedPanel(LPCTSTR splitContainerName, short panel);
BOOL GetFixedPanel(LPCTSTR splitContainerName, short & panel);
BOOL SetIsSplitterFixed(LPCTSTR splitContainerName, BOOL fixed);
BOOL GetIsSplitterFixed(LPCTSTR splitContainerName, BOOL &fixed);
BOOL SetFlowDirection(LPCTSTR flowPanelName, short direction);
BOOL GetFlowDirection(LPCTSTR flowPanelName, short &direction);
BOOL SetFlowItemSpacingX(LPCTSTR flowPanelName, int nSpacing);
BOOL GetFlowItemSpacingX(LPCTSTR flowPanelName, int &nSpacing);
BOOL SetFlowItemSpacingY(LPCTSTR flowPanelName, int nSpacing);
BOOL GetFlowItemSpacingY(LPCTSTR flowPanelName, int &nSpacing);
BOOL SetShowSplitterGrip(LPCTSTR splitContainerName, BOOL bShow);
BOOL GetShowSplitterGrip(LPCTSTR splitContainerName, BOOL & bShow);
void SetShowResizeGrip(ResizeGrip show = RESIZE_GRIP_VISIBLE_ACTIVE_TRIANGLE);
void SetShowResizeGrip(BOOL show);
ResizeGrip GetShowResizeGrip();
BOOL SetSplitterPosition(LPCTSTR splitContainerName, UINT position);
BOOL GetSplitterPosition(LPCTSTR splitContainerName, UINT & position);
BOOL InvokeOnResized();
CString GetDebugInfo();
private:
CWnd * m_pHookedWnd;
CRootPanel root;
CPanel * m_pCaptured;
HCURSOR m_hOldCursor;
int m_splitterOffset;
CUIPanel * CreateUIPanel(UINT uID);
CUIPanel * GetUIPanel(UINT uID);
CString IdToName(UINT uID);
CPanel * FindPanelByName(CPanel * pRoot, LPCTSTR name);
CPanel * FindSplitterFromPoint(CPanel * pRoot, CPoint point);
void GetUIPanels(CPanel * pRoot, CPanelList * pList, BOOL bOle);
void GetVisualPanels(CPanel * pRoot, CPanelList * pList);
void ResizeUI(CPanel * pRoot);
void GetTrueClientRect(CWnd * pWnd, CRect * prc);
void EnsureRootMinMax();
void UpdateSplitterOffset(CPoint ptCurr);
void GetDebugInfo(CPanel * pRoot, CString & info, CString indent);
void OnPaint();
void OnSize(UINT nType, int cx, int cy);
void OnSizing(UINT fwSide, LPRECT pRect);
void OnScroll();
void OnDestroy();
void OnLButtonDown(UINT nFlags, CPoint point);
void OnMouseMove(UINT nFlags, CPoint point);
void OnLButtonUp(UINT nFlags, CPoint point);
LRESULT OnNcHitTest( CPoint point ); void OnThemeChanged();
WNDPROC m_pfnWndProc;
static LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
};
WndResizer.cpp
#include "StdAfx.h"
#include "WndResizer.h"
#include "uxtheme.h"
#pragma comment(lib, "UxTheme.lib")
static CMap<HWND, HWND, CWndResizer *, CWndResizer *> WndResizerData;
class CUIPanel : public CPanel
{
public:
CUIPanel(const CRect * prc, UINT uID);
~CUIPanel();
UINT m_uID; BOOL m_bOle; virtual BOOL SetVisible(BOOL bVisible);
virtual BOOL GetVisible(BOOL &bVisible);
virtual BOOL IsVisible();
virtual CString GetTypeName();
};
class CVisualPanel : public CPanel
{
public:
CVisualPanel();
CVisualPanel(const CRect * prc);
~CVisualPanel();
virtual void Draw(CDC * pDC);
virtual CString GetTypeName();
virtual void OnResized();
private:
CRect m_rcPrev;
};
class CGripperPanel : public CVisualPanel
{
public:
CGripperPanel();
CGripperPanel(const CRect * prc);
~CGripperPanel();
virtual void Draw(CDC * pDC);
virtual CString GetTypeName();
private:
HTHEME m_hTheme;
};
class CSplitterGripperPanel : public CVisualPanel
{
public:
CSplitterGripperPanel(CWndResizer::SplitterOrientation type);
~CSplitterGripperPanel();
virtual void Draw(CDC * pDC);
virtual CString GetTypeName();
private:
CWndResizer::SplitterOrientation m_OrienType;
};
#ifdef USE_SPLIT_PANEL
class CSplitPanel : public CPanel
{
public:
CSplitPanel(CPanel * pPanel);
~CSplitPanel();
virtual BOOL SetAnchor(UINT anchor);
virtual BOOL AddChild(CPanel * prc);
virtual BOOL RemoveChild(CPanel * prc);
virtual CString GetTypeName();
virtual BOOL SetMinSize(CSize & size);
virtual BOOL SetMaxSize(CSize & size);
private:
CPanel * m_pOriginalPanel;
};
#else
typedef CPanel CSplitPanel;
#endif
class CSpitterPanel : public CPanel
{
public:
CSpitterPanel(CWndResizer::SplitterOrientation type);
CSpitterPanel(const CRect * prc, CWndResizer::SplitterOrientation type);
~CSpitterPanel();
virtual CString GetTypeName();
CSplitterGripperPanel * m_pGrippePanel;
private:
CWndResizer::SplitterOrientation m_OrienType;
};
class CSplitContainer : public CPanel
{
public:
CSplitContainer(CSplitPanel * pPanelA, CSplitPanel * pPanelB, CWndResizer::SplitterOrientation type);
~CSplitContainer();
virtual void OnResized();
virtual BOOL AddChild(CPanel * prc);
virtual BOOL RemoveChild(CPanel * prc);
virtual CString GetTypeName();
void SetSplitterPosition(int leftOfSpliter );
int GetSplitterPosition();
void SetFixedPanel(short nFixedPanel );
short GetFixedPanel();
void SetIsSplitterFixed(BOOL bFixed);
BOOL GetIsSplitterFixed();
void SetShowSplitterGrip(BOOL bShow);
BOOL GetShowSplitterGrip();
static CSplitContainer * Create(CPanel * pPanelA, CPanel * pPanelB);
CWndResizer::SplitterOrientation m_Orientation;
private:
BOOL m_IsSplitterFixed;
short m_FixedPanel;
double m_nRatio;
int m_nSplitterSize; void GetSplitArea(CRect * pSplitterPanel);
int GetSplitterSize(CPanel * pLeftPanel, CPanel * pRightPanel);
void UpdateRatio();
CSplitPanel * m_pPanelA;
CSplitPanel * m_pPanelB;
CSpitterPanel * m_pSplitter;
};
class CFlowLayoutPanel : public CPanel
{
public:
CFlowLayoutPanel();
CFlowLayoutPanel(const CRect * prc);
~CFlowLayoutPanel();
virtual void OnResized();
virtual CString GetTypeName();
void SetFlowDirection(CWndResizer::FlowDirection direction);
CWndResizer::FlowDirection GetFlowDirection();
void SetItemSpacingX(int nSpace);
int GetItemSpacingX();
void SetItemSpacingY(int nSpace);
int GetItemSpacingY();
private:
int m_nItemSpacingX;
int m_nItemSpacingY;
CWndResizer::FlowDirection m_nFlowDirection;
};
const TCHAR CWndResizer::ResizeGripperPanelName[] = _T("_resizeGrip");
const TCHAR CWndResizer::RootPanelName[] = _T("_root");
CWndResizer::CWndResizer(void)
{
m_pHookedWnd = NULL;
m_pfnWndProc = NULL;
root.Name = RootPanelName;
m_pCaptured = NULL;
m_hOldCursor = NULL;
m_splitterOffset = 0;
}
CWndResizer::~CWndResizer(void)
{
}
static BOOL CALLBACK MakeGroupBoxesTransparent(HWND hwnd, LPARAM)
{
TCHAR className[128] = _T("");
int iRet = GetClassName(hwnd, className, ARRAYSIZE(className) - 1);
LONG style = GetWindowLong(hwnd, GWL_STYLE);
if ( 0 == _tcscmp(className, _T("Button")) && BS_GROUPBOX == (style & BS_GROUPBOX) ){
CWnd::ModifyStyleEx(hwnd, NULL, WS_EX_TRANSPARENT, NULL);
}
return TRUE;
}
BOOL CWndResizer::Hook(CWnd * pParent)
{
ASSERT( m_pHookedWnd == NULL );
m_pHookedWnd = pParent;
GetTrueClientRect(m_pHookedWnd, &root);
root.m_pHookWnd = m_pHookedWnd;
CRect rcResziGrip(&root);
int cx = ::GetSystemMetrics(SM_CXHSCROLL);
int cy = ::GetSystemMetrics(SM_CYVSCROLL);
rcResziGrip.DeflateRect(root.Width() - cx, root.Height() - cy, 0, 0);
CGripperPanel * pResizeGripper = new CGripperPanel(&rcResziGrip);
pResizeGripper->SetAnchor( ANCHOR_RIGHT | ANCHOR_BOTTOM );
pResizeGripper->Name = ResizeGripperPanelName;
root.AddChild( pResizeGripper );
WndResizerData.SetAt(m_pHookedWnd->m_hWnd, this);
CWnd::ModifyStyle(pParent->GetSafeHwnd(), NULL, WS_CLIPCHILDREN | WS_CLIPSIBLINGS, NULL);
EnumChildWindows(pParent->GetSafeHwnd(), MakeGroupBoxesTransparent, NULL);
m_pfnWndProc = (WNDPROC)::SetWindowLongPtr(m_pHookedWnd->m_hWnd, GWLP_WNDPROC, (LONG_PTR)WindowProc);
return TRUE;
}
BOOL CWndResizer::Hook(CWnd * pParent, CSize & size)
{
ASSERT( m_pHookedWnd == NULL );
m_pHookedWnd = pParent;
GetTrueClientRect(m_pHookedWnd, &root);
root.right = root.left + size.cx;
root.bottom = root.top + size.cy;
root.m_pHookWnd = m_pHookedWnd;
CRect rcResziGrip(&root);
int cx = ::GetSystemMetrics(SM_CXHSCROLL);
int cy = ::GetSystemMetrics(SM_CYVSCROLL);
rcResziGrip.DeflateRect(root.Width() - cx, root.Height() - cy, 0, 0);
CGripperPanel * pResizeGripper = new CGripperPanel(&rcResziGrip);
pResizeGripper->SetAnchor( ANCHOR_RIGHT | ANCHOR_BOTTOM );
pResizeGripper->Name = ResizeGripperPanelName;
root.AddChild( pResizeGripper );
WndResizerData.SetAt(m_pHookedWnd->m_hWnd, this);
CWnd::ModifyStyle(pParent->GetSafeHwnd(), NULL, WS_CLIPCHILDREN | WS_CLIPSIBLINGS, NULL);
EnumChildWindows(pParent->GetSafeHwnd(), MakeGroupBoxesTransparent, NULL);
m_pfnWndProc = (WNDPROC)::SetWindowLongPtr(m_pHookedWnd->m_hWnd, GWLP_WNDPROC, (LONG_PTR)WindowProc);
return TRUE;
}
BOOL CWndResizer::Unhook()
{
if (m_pHookedWnd == NULL )
return FALSE;
WNDPROC pWndProc = (WNDPROC)::SetWindowLongPtr(m_pHookedWnd->m_hWnd, GWLP_WNDPROC, (LONG_PTR)m_pfnWndProc);
WndResizerData.RemoveKey(m_pHookedWnd->m_hWnd);
root.m_pHookWnd = NULL;
m_pHookedWnd = NULL;
while(root.Children.GetCount() > 0 )
{
CPanel * pChild = root.Children.RemoveHead();
delete pChild;
}
return TRUE;
}
BOOL CWndResizer::CreatePanel(UINT uID)
{
ASSERT(m_pHookedWnd != NULL);
if (FindPanelByName(&root, IdToName(uID)) != NULL)
{
return FALSE;
}
CUIPanel * pPanel = GetUIPanel(uID);
ASSERT(pPanel != NULL);
pPanel->m_bOle = TRUE;
return TRUE;
}
BOOL CWndResizer::CreatePanel(LPCTSTR panelName, const CUIntArray * parrID, BOOL setAsChildren)
{
ASSERT(m_pHookedWnd != NULL);
CRect rcFinal(0, 0, 0, 0);
for(int i = 0; i < parrID->GetCount(); i++)
{
CRect rc(0, 0, 0, 0);
m_pHookedWnd->GetDlgItem(parrID->GetAt(i))->GetWindowRect(&rc);
m_pHookedWnd->ScreenToClient(&rc);
rcFinal.UnionRect(&rcFinal, &rc);
}
BOOL bOk = CreatePanel(panelName, &rcFinal);
if (bOk == FALSE)
{
return FALSE;
}
if ( setAsChildren )
{
CPanel * pPanel = FindPanelByName(&root, panelName);
for(int i = 0; i < parrID->GetCount(); i++)
{
if (FindPanelByName(&root, IdToName(parrID->GetAt(i))) != NULL)
{
bOk = root.RemoveChild(pPanel);
ASSERT( bOk );
delete pPanel;
return FALSE;
}
CUIPanel * pUIPanel = GetUIPanel(parrID->GetAt(i));
ASSERT( pUIPanel != NULL);
bOk = pPanel->AddChild( pUIPanel );
ASSERT( bOk );
}
}
return TRUE;
}
BOOL CWndResizer::CreatePanel(LPCTSTR panelName, const UINT * parrID, BOOL setAsChildren)
{
ASSERT(m_pHookedWnd != NULL);
CRect rcFinal(0, 0, 0, 0);
for(int i = 0; parrID[i]; i++)
{
CRect rc(0, 0, 0, 0);
m_pHookedWnd->GetDlgItem(parrID[i])->GetWindowRect(&rc);
m_pHookedWnd->ScreenToClient(&rc);
rcFinal.UnionRect(&rcFinal, &rc);
}
BOOL bOk = CreatePanel(panelName, &rcFinal);
if (bOk == FALSE)
{
return FALSE;
}
if ( setAsChildren )
{
CPanel * pPanel = FindPanelByName(&root, panelName);
for(int i = 0; parrID[i]; i++)
{
if (FindPanelByName(&root, IdToName(parrID[i])) != NULL)
{
bOk = root.RemoveChild(pPanel);
ASSERT( bOk );
delete pPanel;
return FALSE;
}
CUIPanel * pUIPanel = GetUIPanel(parrID[i]);
ASSERT( pUIPanel != NULL);
bOk = pPanel->AddChild( pUIPanel );
ASSERT( bOk );
}
}
return TRUE;
}
BOOL CWndResizer::CreatePanel(LPCTSTR panelName, const CRect * prcPanel)
{
if (FindPanelByName(&root, panelName) != NULL)
return FALSE;
CPanel * pPanel = new CPanel(prcPanel);
pPanel->Name = panelName;
return root.AddChild(pPanel);
}
BOOL CWndResizer::CreateSplitContainer(LPCTSTR panelName, LPCTSTR panelNameA, LPCTSTR panelNameB)
{
CPanel * pPanel = NULL;
if ((pPanel = FindPanelByName(&root, panelName)) != NULL)
return FALSE;
CPanel * pPanelA = NULL;
if ((pPanelA = FindPanelByName(&root, panelNameA)) == NULL)
return FALSE;
CPanel * pPanelB = NULL;
if ((pPanelB = FindPanelByName(&root, panelNameB)) == NULL)
return FALSE;
if (pPanelA == pPanelB) return FALSE;
CPanel * pSplitterContainer = CSplitContainer::Create(pPanelA, pPanelB);
if (pSplitterContainer == NULL)
return FALSE;
pSplitterContainer->Name = panelName;
return root.AddChild(pSplitterContainer);
}
BOOL CWndResizer::CreateSplitContainer(LPCTSTR panelName, LPCTSTR panelNameA, UINT panelIDB)
{
CPanel * pPanel = NULL;
if ((pPanel = FindPanelByName(&root, panelName)) != NULL)
return FALSE;
CPanel * pPanelA = NULL;
if ((pPanelA = FindPanelByName(&root, panelNameA)) == NULL)
return FALSE;
CPanel * pPanelB = GetUIPanel(panelIDB);
if (pPanelB == NULL )
return FALSE;
if (pPanelA == pPanelB) return FALSE;
CPanel * pSplitterContainer = CSplitContainer::Create(pPanelA, pPanelB);
if (pSplitterContainer == NULL)
return FALSE;
pSplitterContainer->Name = panelName;
return root.AddChild(pSplitterContainer);
}
BOOL CWndResizer::CreateSplitContainer(LPCTSTR panelName, UINT panelIDA, LPCTSTR panelNameB)
{
CPanel * pPanel = NULL;
if ((pPanel = FindPanelByName(&root, panelName)) != NULL)
return FALSE;
CPanel * pPanelA = GetUIPanel(panelIDA);
if (pPanelA == NULL )
return FALSE;
CPanel * pPanelB = NULL;
if ((pPanelB = FindPanelByName(&root, panelNameB)) == NULL)
return FALSE;
if (pPanelA == pPanelB) return FALSE;
CPanel * pSplitterContainer = CSplitContainer::Create(pPanelA, pPanelB);
if (pSplitterContainer == NULL)
return FALSE;
pSplitterContainer->Name.Append(panelName);
return root.AddChild(pSplitterContainer);
}
BOOL CWndResizer::CreateSplitContainer(LPCTSTR panelName, UINT panelIDA, UINT panelIDB)
{
CPanel * pPanel = NULL;
if ((pPanel = FindPanelByName(&root, panelName)) != NULL)
return FALSE;
CPanel * pPanelA = GetUIPanel(panelIDA);
if (pPanelA == NULL )
return FALSE;
CPanel * pPanelB = GetUIPanel(panelIDB);
if (pPanelB == NULL )
return FALSE;
if (pPanelA == pPanelB) return FALSE;
CPanel * pSplitterContainer = CSplitContainer::Create(pPanelA, pPanelB);
if (pSplitterContainer == NULL)
return FALSE;
pSplitterContainer->Name = panelName;
return root.AddChild(pSplitterContainer);
}
BOOL CWndResizer::CreateFlowLayoutPanel(LPCTSTR panelName, const CUIntArray * parrID, BOOL setAsChildren)
{
ASSERT(m_pHookedWnd != NULL);
CRect rcFinal(0, 0, 0, 0);
for(int i = 0; i < parrID->GetCount(); i++)
{
CRect rc(0, 0, 0, 0);
m_pHookedWnd->GetDlgItem(parrID->GetAt(i))->GetWindowRect(&rc);
m_pHookedWnd->ScreenToClient(&rc);
rcFinal.UnionRect(&rcFinal, &rc);
}
BOOL bOk = CreateFlowLayoutPanel(panelName, &rcFinal);
if (bOk == FALSE)
{
return FALSE;
}
if ( setAsChildren )
{
CPanel * pPanel = FindPanelByName(&root, panelName);
for(int i = 0; i < parrID->GetCount(); i++)
{
if (FindPanelByName(&root, IdToName(parrID->GetAt(i))) != NULL)
{
bOk = root.RemoveChild(pPanel);
ASSERT( bOk );
delete pPanel;
return FALSE;
}
CUIPanel * pUIPanel = GetUIPanel(parrID->GetAt(i));
ASSERT( pUIPanel != NULL);
bOk = pPanel->AddChild( pUIPanel );
ASSERT( bOk );
}
}
return TRUE;
}
BOOL CWndResizer::CreateFlowLayoutPanel(LPCTSTR panelName, const UINT * parrID, BOOL setAsChildren)
{
ASSERT(m_pHookedWnd != NULL);
CRect rcFinal(0, 0, 0, 0);
for(int i = 0; parrID[i] != 0; i++)
{
CRect rc(0, 0, 0, 0);
m_pHookedWnd->GetDlgItem(parrID[i])->GetWindowRect(&rc);
m_pHookedWnd->ScreenToClient(&rc);
rcFinal.UnionRect(&rcFinal, &rc);
}
BOOL bOk = CreateFlowLayoutPanel(panelName, &rcFinal);
if (bOk == FALSE)
return FALSE;
if ( setAsChildren )
{
CPanel * pPanel = FindPanelByName(&root, panelName);
for(int i = 0; parrID[i] != 0; i++)
{
if (FindPanelByName(&root, IdToName(parrID[i])) != NULL)
{
bOk = root.RemoveChild(pPanel);
ASSERT( bOk );
delete pPanel;
return FALSE;
}
CUIPanel * pUIPanel = GetUIPanel(parrID[i]);
ASSERT( pUIPanel != NULL);
bOk = pPanel->AddChild( pUIPanel );
ASSERT( bOk );
}
}
return TRUE;
}
BOOL CWndResizer::CreateFlowLayoutPanel(LPCTSTR panelName, const CRect * prcPanel)
{
if (FindPanelByName(&root, panelName) != NULL)
{
return FALSE;
}
CPanel * pPanel = new CFlowLayoutPanel(prcPanel);
pPanel->Name = panelName;
return root.AddChild(pPanel);
}
BOOL CWndResizer::SetAnchor(LPCTSTR panelName, UINT uAnchor)
{
CPanel * pPanel = NULL;
if ( (pPanel = FindPanelByName(&root, panelName)) == NULL)
{
return FALSE;
}
return pPanel->SetAnchor(uAnchor);
}
BOOL CWndResizer::SetAnchor(UINT uID, UINT uAnchor)
{
ASSERT(m_pHookedWnd != NULL);
CUIPanel * pPanel = GetUIPanel(uID);
if (pPanel == NULL)
return FALSE;
pPanel->SetAnchor(uAnchor);
return TRUE;
}
BOOL CWndResizer::GetAnchor(LPCTSTR panelName, UINT & anchor)
{
CPanel * pPanel = NULL;
if ( (pPanel = FindPanelByName(&root, panelName)) == NULL) return FALSE;
anchor = pPanel->Anchor;
return TRUE;
}
BOOL CWndResizer::GetAnchor(UINT uID, UINT & anchor)
{
CPanel * pPanel = NULL;
if ( (pPanel = FindPanelByName(&root, IdToName(uID))) == NULL) return FALSE;
anchor = pPanel->Anchor;
return TRUE;
}
BOOL CWndResizer::SetOffset(LPCTSTR panelName, UINT anchor, int offset)
{
CPanel * pPanel = FindPanelByName(&root, panelName);
if (pPanel == NULL)
return FALSE;
return pPanel->SetOffset( anchor, offset );
}
BOOL CWndResizer::SetOffset(UINT uID, UINT anchor, int offset)
{
ASSERT(m_pHookedWnd != NULL);
CUIPanel * pPanel = GetUIPanel(uID);
if (pPanel == NULL)
return FALSE;
return pPanel->SetOffset( anchor, offset );
}
BOOL CWndResizer::SetDock(LPCTSTR panelName, UINT uDock)
{
CPanel * pPanel = NULL;
if ( (pPanel = FindPanelByName(&root, panelName)) == NULL)
{
return FALSE;
}
pPanel->Dock = uDock ;
return TRUE;
}
BOOL CWndResizer::SetDock(UINT uID, UINT uDock)
{
ASSERT(m_pHookedWnd != NULL);
CUIPanel * pPanel = GetUIPanel(uID);
if (pPanel == NULL)
{
return FALSE;
}
pPanel->Dock = uDock;
return TRUE;
}
BOOL CWndResizer::GetDock(LPCTSTR panelName, UINT & uDock)
{
CPanel * pPanel = NULL;
if ( (pPanel = FindPanelByName(&root, panelName)) == NULL) {
return FALSE;
}
uDock = pPanel->Dock;
return TRUE;
}
BOOL CWndResizer::GetDock(UINT uID, UINT & uDock)
{
CPanel * pPanel = NULL;
if ( (pPanel = FindPanelByName(&root, IdToName(uID))) == NULL) {
return FALSE;
}
uDock = pPanel->Dock;
return TRUE;
}
BOOL CWndResizer::SetParent(LPCTSTR panelName, LPCTSTR parentName)
{
ASSERT(m_pHookedWnd != NULL);
CPanel * pParent = NULL;
if ( (pParent = FindPanelByName(&root, parentName)) == NULL) {
return FALSE;
}
CPanel * pPanel = NULL;
if ((pPanel = FindPanelByName(&root, panelName)) == NULL)
{
return FALSE;
}
return pParent->AddChild(pPanel);
}
BOOL CWndResizer::SetParent(UINT uID, LPCTSTR parentName)
{
ASSERT(m_pHookedWnd != NULL);
CPanel * pParent = NULL;
if ( (pParent = FindPanelByName(&root, parentName)) == NULL) {
return FALSE;
}
CPanel * pPanel = NULL;
if ((pPanel = FindPanelByName(&root, IdToName(uID))) == NULL)
{
if ((pPanel = CreateUIPanel(uID)) == NULL)
{
return FALSE;
}
}
return pParent->AddChild(pPanel);
}
BOOL CWndResizer::SetParent(LPCTSTR panelName, UINT uParentID)
{
ASSERT(m_pHookedWnd != NULL);
CPanel * pParent = GetUIPanel(uParentID);
if ( pParent == NULL) {
return FALSE;
}
CPanel * pPanel = NULL;
if ((pPanel = FindPanelByName(&root, panelName)) == NULL)
{
return FALSE;
}
return pParent->AddChild(pPanel);
}
BOOL CWndResizer::SetParent(UINT uID, UINT uParentID)
{
CPanel * pParent = GetUIPanel(uParentID);
if (pParent == NULL)
{
return FALSE;
}
CPanel * pPanel = GetUIPanel(uID);;
if (pParent == NULL)
{
return FALSE;
}
return pParent->AddChild( pPanel );
}
BOOL CWndResizer::GetParent(LPCTSTR panelName, CString & parentName)
{
CPanel * pPanel = NULL;
if ( (pPanel = FindPanelByName(&root, panelName)) == NULL)
{
return FALSE;
}
parentName = pPanel->Parent->Name;
return TRUE;
}
BOOL CWndResizer::GetParent(UINT uID, CString & parentName)
{
CPanel * pPanel = NULL;
if ( (pPanel = FindPanelByName(&root, IdToName(uID))) == NULL) {
return FALSE;
}
parentName = pPanel->Parent->Name;
return TRUE;
}
BOOL CWndResizer::SetMinimumSize( LPCTSTR panelName, CSize & size)
{
CPanel * pPanel = NULL;
if ( (pPanel = FindPanelByName(&root, panelName)) == NULL)
{
return FALSE;
}
return pPanel->SetMinSize( size );
}
BOOL CWndResizer::SetMinimumSize(UINT uID, CSize & size)
{
CPanel * pPanel = NULL;
if ( (pPanel = FindPanelByName(&root, IdToName(uID))) == NULL)
{
if ((pPanel = CreateUIPanel(uID)) == NULL)
{
return FALSE;
}
}
return pPanel->SetMinSize( size );
}
BOOL CWndResizer::GetMinimumSize(LPCTSTR panelName, CSize & size)
{
CPanel * pPanel = NULL;
if ( (pPanel = FindPanelByName(&root, panelName)) == NULL)
{
return FALSE;
}
size = pPanel->MinSize;
return TRUE;
}
BOOL CWndResizer::GetMinimumSize(UINT uID, CSize & size)
{
const CPanel * pPanel = NULL;
if ( (pPanel = FindPanelByName(&root, IdToName(uID))) == NULL)
{
return FALSE;
}
size = pPanel->MinSize;
return TRUE;
}
BOOL CWndResizer::SetMaximumSize(UINT uID, CSize & size)
{
CPanel * pPanel = NULL;
if ( (pPanel = FindPanelByName(&root, IdToName(uID))) == NULL)
{
return FALSE;
}
return pPanel->SetMaxSize(size);
}
BOOL CWndResizer::SetMaximumSize( LPCTSTR panelName, CSize & size)
{
CPanel * pPanel = NULL;
if ( (pPanel = FindPanelByName(&root, panelName)) == NULL)
{
return FALSE;
}
return pPanel->SetMaxSize(size);
}
BOOL CWndResizer::GetMaximumSize( LPCTSTR panelName, CSize & size)
{
CPanel * pPanel = NULL;
if ( (pPanel = FindPanelByName(&root, panelName)) == NULL)
{
return FALSE;
}
size = pPanel->MaxSize;
return TRUE;
}
BOOL CWndResizer::GetMaximumSize( UINT uID, CSize & size)
{
CPanel * pPanel = NULL;
if ( (pPanel = FindPanelByName(&root, IdToName(uID))) == NULL)
{
return FALSE;
}
size = pPanel->MaxSize;
return TRUE;
}
BOOL CWndResizer::SetFixedPanel(LPCTSTR splitContainerName, short panel)
{
CPanel * pContainer = FindPanelByName(&root, splitContainerName);
if (pContainer == NULL)
{
return FALSE;
}
CSplitContainer * pSplitContainer = dynamic_cast<CSplitContainer *>( pContainer );
if (pSplitContainer == NULL)
{
return FALSE;
}
pSplitContainer->SetFixedPanel(panel);
return TRUE;
}
BOOL CWndResizer::GetFixedPanel(LPCTSTR splitContainerName, short & panel)
{
CPanel * pContainer = FindPanelByName(&root, splitContainerName);
if (pContainer == NULL)
{
return FALSE;
}
CSplitContainer * pSplitContainer = dynamic_cast<CSplitContainer *> (pContainer);
if (pSplitContainer == NULL)
{
return FALSE;
}
panel = pSplitContainer->GetFixedPanel();
return TRUE;
}
BOOL CWndResizer::SetIsSplitterFixed(LPCTSTR splitContainerName, BOOL fixed)
{
CPanel * pContainer = FindPanelByName(&root, splitContainerName);
if (pContainer == NULL)
{
return FALSE;
}
CSplitContainer * pSplitContainer = dynamic_cast<CSplitContainer *> (pContainer);
if (pSplitContainer == NULL)
{
return FALSE;
}
pSplitContainer->SetIsSplitterFixed( fixed );
return TRUE;
}
BOOL CWndResizer::GetIsSplitterFixed(LPCTSTR splitContainerName, BOOL &fixed)
{
CPanel * pContainer = FindPanelByName(&root, splitContainerName);
if (pContainer == NULL)
{
return FALSE;
}
CSplitContainer * pSplitContainer = dynamic_cast<CSplitContainer *> (pContainer);
if (pSplitContainer == NULL)
{
return FALSE;
}
fixed = pSplitContainer->GetIsSplitterFixed();
return TRUE;
}
BOOL CWndResizer::SetShowSplitterGrip(LPCTSTR splitContainerName, BOOL bShow)
{
CPanel * pContainer = FindPanelByName(&root, splitContainerName);
if (pContainer == NULL)
{
return FALSE;
}
CSplitContainer * pSplitContainer = dynamic_cast<CSplitContainer *> (pContainer);
if (pSplitContainer == NULL)
{
return FALSE;
}
pSplitContainer->SetShowSplitterGrip( bShow );
return TRUE;
}
BOOL CWndResizer::GetShowSplitterGrip(LPCTSTR splitContainerName, BOOL &bShow)
{
CPanel * pContainer = FindPanelByName(&root, splitContainerName);
if (pContainer == NULL)
{
return FALSE;
}
CSplitContainer * pSplitContainer = dynamic_cast<CSplitContainer *> (pContainer);
if (pSplitContainer == NULL)
{
return FALSE;
}
bShow = pSplitContainer->GetShowSplitterGrip();
return TRUE;
}
void CWndResizer::SetShowResizeGrip(CWndResizer::ResizeGrip show)
{
CGripperPanel * pPanel = (CGripperPanel *)FindPanelByName(&root, ResizeGripperPanelName);
ASSERT(pPanel != NULL);
if ( pPanel->m_bVisible != show )
{
pPanel->m_bVisible = show;
m_pHookedWnd->Invalidate(TRUE);
}
}
void CWndResizer::SetShowResizeGrip(BOOL show)
{
SetShowResizeGrip( show ? RESIZE_GRIP_VISIBLE_ACTIVE_TRIANGLE : RESIZE_GRIP_HIDDEN );
}
CWndResizer::ResizeGrip CWndResizer::GetShowResizeGrip()
{
CGripperPanel * pPanel = (CGripperPanel *)FindPanelByName(&root, ResizeGripperPanelName);
ASSERT(pPanel != NULL);
return (CWndResizer::ResizeGrip)pPanel->m_bVisible;
}
BOOL CWndResizer::SetFlowDirection(LPCTSTR flowPanelName, short direction)
{
ASSERT(m_pHookedWnd != NULL);
CPanel * pPanel = NULL;
if ((pPanel = FindPanelByName(&root, flowPanelName)) == NULL)
{
return FALSE;
}
CFlowLayoutPanel * pFlowLayout = dynamic_cast<CFlowLayoutPanel *> ( pPanel);
if (pFlowLayout == NULL)
{
return FALSE;
}
pFlowLayout->SetFlowDirection( direction == 1 ? CWndResizer::LEFT_TO_RIGHT : CWndResizer::TOP_TO_BOTTOM);
return TRUE;
}
BOOL CWndResizer::GetFlowDirection(LPCTSTR flowPanelName, short &direction)
{
ASSERT(m_pHookedWnd != NULL);
CPanel * pPanel = NULL;
if ((pPanel = FindPanelByName(&root, flowPanelName)) == NULL)
{
return FALSE;
}
CFlowLayoutPanel * pFlowLayout = dynamic_cast<CFlowLayoutPanel *> ( pPanel);
if (pFlowLayout == NULL)
{
return FALSE;
}
direction = (pFlowLayout->GetFlowDirection() == CWndResizer::LEFT_TO_RIGHT ? 1 : 2);
return TRUE;
}
BOOL CWndResizer::SetFlowItemSpacingX(LPCTSTR flowPanelName, int nSpacing)
{
ASSERT(m_pHookedWnd != NULL);
CPanel * pPanel = NULL;
if ((pPanel = FindPanelByName(&root, flowPanelName)) == NULL)
{
return FALSE;
}
CFlowLayoutPanel * pFlowLayout = dynamic_cast<CFlowLayoutPanel *> ( pPanel);
if (pFlowLayout == NULL)
{
return FALSE;
}
pFlowLayout->SetItemSpacingX(nSpacing);
return TRUE;
}
BOOL CWndResizer::GetFlowItemSpacingX(LPCTSTR flowPanelName, int &nSpacing)
{
ASSERT(m_pHookedWnd != NULL);
CPanel * pPanel = NULL;
if ((pPanel = FindPanelByName(&root, flowPanelName)) == NULL)
return FALSE;
CFlowLayoutPanel * pFlowLayout = dynamic_cast<CFlowLayoutPanel *> ( pPanel);
if (pFlowLayout == NULL)
return FALSE;
nSpacing = pFlowLayout->GetItemSpacingX();
return TRUE;
}
BOOL CWndResizer::SetFlowItemSpacingY(LPCTSTR flowPanelName, int nSpacing)
{
ASSERT(m_pHookedWnd != NULL);
CPanel * pPanel = NULL;
if ((pPanel = FindPanelByName(&root, flowPanelName)) == NULL)
return FALSE;
CFlowLayoutPanel * pFlowLayout = dynamic_cast<CFlowLayoutPanel *> ( pPanel);
if (pFlowLayout == NULL)
return FALSE;
pFlowLayout->SetItemSpacingY(nSpacing);
return TRUE;
}
BOOL CWndResizer::GetFlowItemSpacingY(LPCTSTR flowPanelName, int &nSpacing)
{
ASSERT(m_pHookedWnd != NULL);
CPanel * pPanel = NULL;
if ((pPanel = FindPanelByName(&root, flowPanelName)) == NULL)
return FALSE;
CFlowLayoutPanel * pFlowLayout = dynamic_cast<CFlowLayoutPanel *> ( pPanel);
if (pFlowLayout == NULL)
return FALSE;
nSpacing = pFlowLayout->GetItemSpacingY();
return TRUE;
}
CPanel * CWndResizer::FindPanelByName(CPanel * pRoot, LPCTSTR name)
{
if (CString(name).GetLength() == 0)
return NULL;
if (pRoot == NULL )
return NULL;
if (pRoot->Name.CompareNoCase(name) == 0)
return pRoot;
POSITION pos = pRoot->Children.GetHeadPosition();
while(pos != NULL)
{
CPanel * pChild = pRoot->Children.GetNext(pos);
CPanel * pFound = FindPanelByName(pChild, name);
if (pFound != NULL )
return pFound;
}
return NULL;
}
void CWndResizer::GetUIPanels(CPanel * pRoot, CPanelList * pList, BOOL bOle)
{
if (pRoot == NULL )
{
return ;
}
CUIPanel * pUIPanel = dynamic_cast<CUIPanel *> ( pRoot);
if (pUIPanel != NULL && pUIPanel->m_bOle == bOle)
{
pList->AddTail( pRoot );
}
POSITION pos = pRoot->Children.GetHeadPosition();
while(pos != NULL)
{
CPanel * pChild = pRoot->Children.GetNext(pos);
GetUIPanels(pChild, pList, bOle);
}
}
void CWndResizer::GetVisualPanels(CPanel * pRoot, CPanelList * pList)
{
if (pRoot == NULL )
{
return ;
}
CVisualPanel * pUIPanel = dynamic_cast<CVisualPanel *> ( pRoot);
if (pUIPanel != NULL)
{
pList->AddTail( pRoot );
}
POSITION pos = pRoot->Children.GetHeadPosition();
while(pos != NULL)
{
CPanel * pChild = pRoot->Children.GetNext(pos);
GetVisualPanels(pChild, pList);
}
}
CPanel * CWndResizer::FindSplitterFromPoint(CPanel * pRoot, CPoint point)
{
if (pRoot == NULL )
{
return NULL;
}
CSpitterPanel * pSpitterPanel = dynamic_cast<CSpitterPanel *>(pRoot);
if (pSpitterPanel != NULL && pRoot->PtInRect(point) == TRUE )
{
CSplitContainer * pContainer = (CSplitContainer *)pRoot->Parent;
if (!pContainer->GetIsSplitterFixed())
{
CPoint ptScreen = point;
m_pHookedWnd->ClientToScreen(&ptScreen);
HWND hWndFromPoint = ::WindowFromPoint(ptScreen);
if (m_pHookedWnd->m_hWnd == hWndFromPoint)
{
return pRoot;
}
}
}
POSITION pos = pRoot->Children.GetHeadPosition();
while(pos != NULL)
{
CPanel * pChild = pRoot->Children.GetNext(pos);
CPanel * pFound = FindSplitterFromPoint(pChild, point);
if (pFound != NULL )
{
return pFound;
}
}
return NULL;
}
CString CWndResizer::IdToName(UINT uID)
{
CString sName;
sName.Format(_T("%d"), uID);
return sName;
}
CUIPanel * CWndResizer::CreateUIPanel(UINT uID)
{
ASSERT(m_pHookedWnd != NULL);
CWnd * pWnd = m_pHookedWnd->GetDlgItem(uID);
if ( pWnd == NULL )
{
return NULL;
}
CRect rc(0, 0, 0, 0);
pWnd->GetWindowRect( &rc );
m_pHookedWnd->ScreenToClient( &rc );
CUIPanel * pPanel = new CUIPanel(&rc, uID);
pPanel->Name = IdToName(uID);
return pPanel ;
}
CUIPanel * CWndResizer::GetUIPanel(UINT uID)
{
CUIPanel * pPanel = NULL;
if ((pPanel = (CUIPanel *)FindPanelByName(&root, IdToName(uID))) == NULL)
{
pPanel = CreateUIPanel(uID);
if (pPanel != NULL)
{
root.AddChild( pPanel );
}
}
return pPanel;
}
BOOL CWndResizer::SetSplitterPosition(LPCTSTR splitContainerName, UINT position)
{
ASSERT(m_pHookedWnd != NULL);
CPanel * pPanel = NULL;
if ((pPanel = FindPanelByName(&root, splitContainerName)) == NULL)
return FALSE;
CSplitContainer * pContainer = dynamic_cast<CSplitContainer *> ( pPanel);
if (pContainer == NULL)
return FALSE;
pContainer->SetSplitterPosition( (int) position);
ResizeUI( pContainer );
return TRUE;
}
BOOL CWndResizer::GetSplitterPosition(LPCTSTR splitContainerName, UINT & position)
{
ASSERT(m_pHookedWnd != NULL);
CPanel * pPanel = NULL;
if ((pPanel = FindPanelByName(&root, splitContainerName)) == NULL)
return FALSE;
CSplitContainer * pContainer = dynamic_cast<CSplitContainer *> ( pPanel);
if (pContainer == NULL)
return FALSE;
position = (UINT) pContainer->GetSplitterPosition();
return TRUE;
}
BOOL CWndResizer::InvokeOnResized()
{
ASSERT(m_pHookedWnd != NULL);
OnSize(0, 0, 0);
return TRUE;
}
CString CWndResizer::GetDebugInfo()
{
ASSERT(m_pHookedWnd != NULL);
CString sInfo;
CString sIndent;
GetDebugInfo(&root, sInfo, sIndent);
return sInfo;
}
void CWndResizer::GetDebugInfo(CPanel * pRoot, CString & info, CString indent)
{
if (pRoot == NULL )
return ;
info.Append(_T("\n"));
info.Append(indent);
info.Append(pRoot->ToString() );
indent.Append(_T(" "));
for(int i = 0; i < pRoot->Children.GetCount(); i++)
{
CPanel * pChild = pRoot->Children.GetAt(pRoot->Children.FindIndex(i));
GetDebugInfo(pChild, info, indent);
}
}
void CWndResizer::ResizeUI(CPanel * pRoot)
{
CPanelList panels;
GetUIPanels(pRoot, &panels, FALSE);
POSITION pos = NULL;
if (panels.GetCount() > 0)
{
HDWP hDWP = ::BeginDeferWindowPos((int)panels.GetCount());
ASSERT( hDWP != NULL);
pos = panels.GetHeadPosition();
while (pos != NULL)
{
CUIPanel * pPanel = (CUIPanel *) panels.GetNext(pos);
::DeferWindowPos(hDWP, m_pHookedWnd->GetDlgItem(pPanel->m_uID)->m_hWnd, NULL,
pPanel->left , pPanel->top , pPanel->Width(), pPanel->Height(),
SWP_NOACTIVATE | SWP_NOZORDER );
}
BOOL bOk = ::EndDeferWindowPos(hDWP);
ASSERT( bOk );
m_pHookedWnd->InvalidateRect(pRoot, FALSE);
}
panels.RemoveAll();
GetUIPanels(pRoot, &panels, TRUE);
pos = panels.GetHeadPosition();
while (pos != NULL)
{
CUIPanel * pPanel = (CUIPanel *) panels.GetNext(pos);
m_pHookedWnd->GetDlgItem(pPanel->m_uID)->MoveWindow(pPanel);
}
}
void CWndResizer::OnLButtonDown(UINT nFlags, CPoint point)
{
UpdateSplitterOffset(point);
}
void CWndResizer::OnMouseMove(UINT nFlags, CPoint point)
{
if (m_pCaptured != NULL )
{
if ((nFlags & MK_LBUTTON) <= 0)
{
CPoint ptScreen = point;
m_pHookedWnd->ClientToScreen(&ptScreen);
HWND hWndFromPoint = ::WindowFromPoint(ptScreen);
if (m_pCaptured->PtInRect( point ) == FALSE || hWndFromPoint != m_pHookedWnd->m_hWnd)
{
::ReleaseCapture();
m_pCaptured = NULL;
HCURSOR hCur = ::SetCursor(m_hOldCursor);
::DestroyCursor( hCur );
m_hOldCursor = NULL;
}
}
}
if (m_pCaptured == NULL )
{
m_pCaptured = FindSplitterFromPoint(&root, point);
if (m_pCaptured != NULL)
{
m_pHookedWnd->SetCapture();
LPCTSTR cursor = NULL;
CSplitContainer * pSplitContainer = (CSplitContainer *)m_pCaptured->Parent;
if (pSplitContainer->m_Orientation == CWndResizer::SPLIT_CONTAINER_H)
{
cursor = IDC_SIZEWE;
}
else
{
cursor = IDC_SIZENS;
}
HCURSOR hCur = AfxGetApp()->LoadStandardCursor(cursor);
HCURSOR m_hOldCursor = ::SetCursor(hCur);
}
}
if (m_pCaptured != NULL && (nFlags & MK_LBUTTON) > 0)
{
CSplitContainer * pSplitterContainer = (CSplitContainer *) m_pCaptured->Parent;
if (pSplitterContainer->m_Orientation == CWndResizer::SPLIT_CONTAINER_H)
{
pSplitterContainer->SetSplitterPosition( point.x - m_splitterOffset);
}
else
{
pSplitterContainer->SetSplitterPosition( point.y - m_splitterOffset);
}
UpdateSplitterOffset(point);
ResizeUI(pSplitterContainer);
}
}
void CWndResizer::OnLButtonUp(UINT nFlags, CPoint point)
{
OnMouseMove(nFlags, point);
}
void CWndResizer::GetTrueClientRect(CWnd * pWnd, CRect * prc)
{
int nMin = 0;
int nMax = 0;
int nCur = 0;
pWnd->GetClientRect(prc);
if ( (pWnd->GetStyle() & WS_HSCROLL) > 0)
{
pWnd->GetScrollRange(SB_HORZ, &nMin, &nMax);
nCur = pWnd->GetScrollPos(SB_HORZ);
prc->right = prc->left + nMax;
prc->OffsetRect( -nCur , 0);
}
if ( (pWnd->GetStyle() & WS_VSCROLL) > 0)
{
pWnd->GetScrollRange(SB_VERT, &nMin, &nMax);
nCur = pWnd->GetScrollPos(SB_VERT);
prc->bottom = prc->top + nMax;
prc->OffsetRect(0, -nCur);
}
}
void CWndResizer::EnsureRootMinMax()
{
if (root.Width() < root.MinSize.cx)
root.right = root.left + root.MinSize.cx;
if (root.Width() > root.MaxSize.cx)
root.right = root.left + root.MaxSize.cx;
if (root.Height() < root.MinSize.cy)
root.bottom = root.top + root.MinSize.cy;
if (root.Height() > root.MaxSize.cy)
root.bottom = root.top + root.MaxSize.cy;
}
void CWndResizer::UpdateSplitterOffset(CPoint ptCurr)
{
if (m_pCaptured == NULL )
return;
if (((CSplitContainer *)m_pCaptured->Parent)->m_Orientation == CWndResizer::SPLIT_CONTAINER_H)
{
if ( ptCurr.x < m_pCaptured->left)
{
m_splitterOffset = 0;
}
else if ( ptCurr.x > m_pCaptured->right)
{
m_splitterOffset = m_pCaptured->Width();
}
else
{
m_splitterOffset = ptCurr.x - m_pCaptured->left;
}
}
else
{
if ( ptCurr.y < m_pCaptured->top)
{
m_splitterOffset = 0;
}
else if ( ptCurr.y > m_pCaptured->bottom)
{
m_splitterOffset = m_pCaptured->Height();
}
else
{
m_splitterOffset = ptCurr.y - m_pCaptured->top;
}
}
}
void CWndResizer::OnSizing(UINT fwSide, LPRECT pRect)
{
CRect * prc = (CRect *) pRect;
CRect rcMin(0, 0, root.MinSize.cx, root.MinSize.cy);
CRect rcMax(0, 0, root.MaxSize.cx, root.MaxSize.cy);
LONG_PTR style = GetWindowLongPtr(m_pHookedWnd->m_hWnd , GWL_STYLE);
LONG_PTR styleEx = GetWindowLongPtr(m_pHookedWnd->m_hWnd, GWL_EXSTYLE);
::AdjustWindowRectEx(&rcMin, (DWORD)style, (m_pHookedWnd->GetMenu() != NULL), (DWORD)styleEx);
::AdjustWindowRectEx(&rcMax, (DWORD)style, (m_pHookedWnd->GetMenu() != NULL), (DWORD)styleEx);
switch (fwSide)
{
case WMSZ_BOTTOM:
if (prc->Height() < rcMin.Height() )
{
prc->bottom = prc->top + rcMin.Height();
}
if (prc->Height() > rcMax.Height() )
{
prc->bottom = prc->top + rcMax.Height();
}
break;
case WMSZ_BOTTOMLEFT:
if (prc->Height() < rcMin.Height() )
{
prc->bottom = prc->top + rcMin.Height();
}
if (prc->Width() < rcMin.Width() )
{
prc->left = prc->right - rcMin.Width();
}
if (prc->Height() > rcMax.Height() )
{
prc->bottom = prc->top + rcMax.Height();
}
if (prc->Width() > rcMax.Width() )
{
prc->left = prc->right - rcMax.Width();
}
break;
case WMSZ_BOTTOMRIGHT:
if (prc->Height() < rcMin.Height() )
{
prc->bottom = prc->top + rcMin.Height();
}
if (prc->Width() < rcMin.Width() )
{
prc->right = prc->left + rcMin.Width();
}
if (prc->Height() > rcMax.Height() )
{
prc->bottom = prc->top + rcMax.Height();
}
if (prc->Width() > rcMax.Width() )
{
prc->right = prc->left + rcMax.Width();
}
break;
case WMSZ_LEFT:
if (prc->Width() < rcMin.Width() )
{
prc->left = prc->right - rcMin.Width();
}
if (prc->Width() > rcMax.Width() )
{
prc->left = prc->right - rcMax.Width();
}
break;
case WMSZ_RIGHT:
if (prc->Width() < rcMin.Width() )
{
prc->right = prc->left + rcMin.Width();
}
if (prc->Width() > rcMax.Width() )
{
prc->right = prc->left + rcMax.Width();
}
break;
case WMSZ_TOP:
if (prc->Height() < rcMin.Height() )
{
prc->top = prc->bottom - rcMin.Height();
}
if (prc->Height() > rcMax.Height() )
{
prc->top = prc->bottom - rcMax.Height();
}
break;
case WMSZ_TOPLEFT:
if (prc->Height() < rcMin.Height() )
{
prc->top = prc->bottom - rcMin.Height();
}
if (prc->Width() < rcMin.Width() )
{
prc->left = prc->right - rcMin.Width();
}
if (prc->Height() > rcMax.Height() )
{
prc->top = prc->bottom - rcMax.Height();
}
if (prc->Width() > rcMax.Width() )
{
prc->left = prc->right - rcMax.Width();
}
break;
case WMSZ_TOPRIGHT:
if (prc->Height() < rcMin.Height() )
{
prc->top = prc->bottom - rcMin.Height();
}
if (prc->Width() < rcMin.Width() )
{
prc->right = prc->left + rcMin.Width();
}
if (prc->Height() > rcMax.Height() )
{
prc->top = prc->bottom - rcMax.Height();
}
if (prc->Width() > rcMax.Width() )
{
prc->right = prc->left + rcMax.Width();
}
break;
}
}
void CWndResizer::OnPaint()
{
if (m_pHookedWnd == NULL)
{
return;
}
CDC* pDC = m_pHookedWnd->GetDC();
CPanelList panelList;
GetVisualPanels(&root, &panelList);
POSITION pos = panelList.GetHeadPosition();
while (pos != NULL)
{
CVisualPanel * pPanel = (CVisualPanel *) panelList.GetNext(pos);
if (pPanel->m_bVisible)
{
pPanel->Draw(pDC);
}
}
}
void CWndResizer::OnThemeChanged()
{
if (m_pHookedWnd == NULL)
return;
CGripperPanel * pPanel = (CGripperPanel *)FindPanelByName(&root, ResizeGripperPanelName);
ASSERT(pPanel != NULL);
if( pPanel->m_bVisible != RESIZE_GRIP_HIDDEN )
{
GetTrueClientRect(m_pHookedWnd, &root);
EnsureRootMinMax();
root.OnResized();
ResizeUI(&root);
}
}
LRESULT CWndResizer::OnNcHitTest( CPoint point )
{
CGripperPanel * pPanel = (CGripperPanel *)FindPanelByName(&root, ResizeGripperPanelName);
if( !pPanel || !pPanel->m_bVisible )
return HTNOWHERE;
ASSERT( m_pHookedWnd != NULL );
m_pHookedWnd->ScreenToClient( &point );
if( pPanel->m_bVisible == RESIZE_GRIP_VISIBLE_ACTIVE_TRIANGLE )
{
if( pPanel->PtInTriangle(point) )
return HTBOTTOMRIGHT;
}
else if( pPanel->m_bVisible == RESIZE_GRIP_VISIBLE_ACTIVE_RECT )
{
if( pPanel->PtInRect( point ) )
return HTBOTTOMRIGHT;
}
return HTNOWHERE;
}
void CWndResizer::OnSize(UINT nType, int cx, int cy)
{
GetTrueClientRect(m_pHookedWnd, &root);
EnsureRootMinMax();
root.OnResized();
ResizeUI(&root);
}
void CWndResizer::OnScroll()
{
GetTrueClientRect(m_pHookedWnd, &root);
EnsureRootMinMax();
root.OnResized();
ResizeUI(&root);
}
void CWndResizer::OnDestroy()
{
if (m_pHookedWnd != NULL)
{
Unhook();
}
}
LRESULT CALLBACK CWndResizer::WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
CWndResizer * pResizer = NULL;
WndResizerData.Lookup(hWnd, pResizer);
ASSERT( pResizer != NULL);
LRESULT lResult;
switch (uMsg)
{
case WM_SIZE:
{
int cx = LOWORD(lParam);
int cy = HIWORD(lParam);
pResizer->OnSize((UINT) wParam, cx, cy);
break;
}
case WM_SIZING:
pResizer->OnSizing((UINT) wParam, (LPRECT)lParam);
break;
case WM_DESTROY:
pResizer->OnDestroy();
break;
case WM_MOUSEMOVE:
pResizer->OnMouseMove((UINT) wParam, CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)));
break;
case WM_LBUTTONDOWN:
pResizer->OnLButtonDown((UINT) wParam, CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)));
break;
case WM_LBUTTONUP:
pResizer->OnLButtonUp((UINT) wParam, CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)));
break;
case WM_PAINT:
pResizer->OnPaint();
break;
case WM_HSCROLL:
case WM_VSCROLL:
pResizer->OnScroll();
break;
case WM_NCHITTEST:
lResult = pResizer->OnNcHitTest( CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)) );
if( lResult != HTNOWHERE )
return lResult;
break;
default:
break;
}
lResult = ::CallWindowProc(pResizer->m_pfnWndProc, hWnd, uMsg, wParam, lParam);
switch( uMsg )
{
case WM_SYSCOLORCHANGE:
case WM_THEMECHANGED:
pResizer->OnThemeChanged();
break;
}
return lResult;
}
CPanel::CPanel() : CRect(0, 0, 0, 0)
{
Init();
}
CPanel::CPanel(const CRect * prc) : CRect(prc)
{
Init();
}
void CPanel::Init()
{
Parent = NULL;
LeftOffset = 0;
TopOffset = 0;
RightOffset = 0;
BottomOffset = 0;
MinSize.SetSize(10, 10);
MaxSize.SetSize(100000, 100000);
Anchor = (ANCHOR_LEFT | ANCHOR_TOP);
Dock = DOCK_NONE;
m_bVisible = TRUE;
}
CPanel::~CPanel()
{
while(Children.GetCount() > 0 )
{
delete Children.RemoveHead();
}
}
void CPanel::OnResized()
{
BOOL bOk = FALSE;
CRect rcEmpty(this);
POSITION pos = Children.GetHeadPosition();
while(pos != NULL)
{
CPanel * pChild = Children.GetNext(pos);
if (pChild->Dock != DOCK_NONE)
{
switch(pChild->Dock)
{
case DOCK_LEFT:
pChild->SetRect(rcEmpty.left, rcEmpty.top, rcEmpty.left + pChild->Width(), rcEmpty.bottom);
bOk = rcEmpty.SubtractRect(&rcEmpty, pChild);
break;
case DOCK_TOP:
pChild->SetRect(rcEmpty.left, rcEmpty.top, rcEmpty.right, rcEmpty.top + pChild->Height());
bOk = rcEmpty.SubtractRect(&rcEmpty, pChild);
break;
case DOCK_RIGHT:
pChild->SetRect(rcEmpty.right - pChild->Width(), rcEmpty.top, rcEmpty.right, rcEmpty.bottom);
bOk = rcEmpty.SubtractRect(&rcEmpty, pChild);
break;
case DOCK_BOTTOM:
pChild->SetRect(rcEmpty.left, rcEmpty.bottom - pChild->Height(), rcEmpty.right, rcEmpty.bottom);
bOk = rcEmpty.SubtractRect(&rcEmpty, pChild);
break;
case DOCK_FILL:
pChild->SetRect(rcEmpty.left, rcEmpty.top, rcEmpty.right, rcEmpty.bottom);
break;
}
pChild->OnResized();
continue;
}
CRect rc(0, 0, 0, 0);
if ((pChild->Anchor & ANCHOR_HORIZONTALLY_CENTERED) == ANCHOR_HORIZONTALLY_CENTERED )
{
rc.left = this->left + ((int)( (this->Width() - pChild->Width()) / 2));
rc.right = rc.left + pChild->Width();
BOOL bReposition = FALSE;
if (pChild->MinSize.cx > rc.Width() )
{
bReposition = TRUE;
rc.right = rc.left + pChild->MinSize.cx;
}
if (pChild->MaxSize.cx < rc.Width() )
{
bReposition = TRUE;
rc.right = rc.left + pChild->MaxSize.cx;
}
if (bReposition)
{
int nWidth = rc.Width();
rc.left = (int)( (this->Width() - nWidth) / 2) ;
rc.right = rc.left + nWidth;
}
}
else if ((pChild->Anchor & ANCHOR_HORIZONTALLY) == ANCHOR_HORIZONTALLY )
{
rc.left = this->left + pChild->LeftOffset;
rc.right = this->right - pChild->RightOffset;
if ((pChild->Anchor & ANCHOR_PRIORITY_RIGHT) == ANCHOR_PRIORITY_RIGHT)
{
if (pChild->MinSize.cx > rc.Width() )
{
rc.left = rc.right - pChild->MinSize.cx;
}
if (pChild->MaxSize.cx < rc.Width() )
{
rc.left = rc.right - pChild->MaxSize.cx;
}
}
else
{
if (pChild->MinSize.cx > rc.Width() )
{
rc.right = rc.left + pChild->MinSize.cx;
}
if (pChild->MaxSize.cx < rc.Width() )
{
rc.right = rc.left + pChild->MaxSize.cx;
}
}
}
else if ((pChild->Anchor & ANCHOR_RIGHT) == ANCHOR_RIGHT )
{
rc.right = this->right - pChild->RightOffset;
rc.left = rc.right - pChild->Width();
if (pChild->MinSize.cx > rc.Width() )
{
rc.left = rc.right - pChild->MinSize.cx;
}
if (pChild->MaxSize.cx < rc.Width() )
{
rc.left = rc.right - pChild->MaxSize.cx;
}
}
else if ((pChild->Anchor & ANCHOR_LEFT) == ANCHOR_LEFT )
{
rc.left = this->left + pChild->LeftOffset;
rc.right = rc.left + pChild->Width();
if (pChild->MinSize.cx > rc.Width() )
{
rc.right = rc.left + pChild->MinSize.cx;
}
if (pChild->MaxSize.cx < rc.Width() )
{
rc.right = rc.left + pChild->MaxSize.cx;
}
}
else
{
ASSERT( FALSE );
}
if ((pChild->Anchor & ANCHOR_VERTICALLY_CENTERED) == ANCHOR_VERTICALLY_CENTERED )
{
rc.top = this->top + ((int)( (this->Height() - pChild->Height()) / 2));
rc.bottom = rc.top + pChild->Height();
BOOL bReposition = FALSE;
if (pChild->MinSize.cy > rc.Height() )
{
bReposition = TRUE;
rc.bottom = rc.top + pChild->MinSize.cy;
}
if (pChild->MaxSize.cy < rc.Height() )
{
bReposition = TRUE;
rc.bottom = rc.top + pChild->MaxSize.cy;
}
if (bReposition)
{
int nHeight = rc.Height();
rc.top = (int)( (this->Height() - nHeight) / 2);
rc.bottom = rc.top + nHeight;
}
}
else if ((pChild->Anchor & ANCHOR_VERTICALLY ) == ANCHOR_VERTICALLY )
{
rc.top = this->top + pChild->TopOffset;
rc.bottom = this->bottom - pChild->BottomOffset;
if ((pChild->Anchor & ANCHOR_PRIORITY_BOTTOM) == ANCHOR_PRIORITY_BOTTOM)
{
if (pChild->MinSize.cy > rc.Height() )
{
rc.top = rc.bottom - pChild->MinSize.cy;
}
if (pChild->MaxSize.cy < rc.Height() )
{
rc.top = rc.bottom - pChild->MaxSize.cy;
}
}
else
{
if (pChild->MinSize.cy > rc.Height() )
{
rc.bottom = rc.top + pChild->MinSize.cy;
}
if (pChild->MaxSize.cy < rc.Height() )
{
rc.bottom = rc.top + pChild->MaxSize.cy;
}
}
}
else if ((pChild->Anchor & ANCHOR_BOTTOM) == ANCHOR_BOTTOM )
{
rc.bottom = this->bottom - pChild->BottomOffset;
rc.top = rc.bottom - pChild->Height();
if (pChild->MinSize.cy > rc.Height() )
{
rc.top = rc.bottom - pChild->MinSize.cy;
}
if (pChild->MaxSize.cy < rc.Height() )
{
rc.top = rc.bottom - pChild->MaxSize.cy;
}
}
else if ((pChild->Anchor & ANCHOR_TOP) == ANCHOR_TOP )
{
rc.top = this->top + pChild->TopOffset;
rc.bottom = rc.top + pChild->Height();
if (pChild->MinSize.cy > rc.Height() )
{
rc.bottom = rc.top + pChild->MinSize.cy;
}
if (pChild->MaxSize.cy < rc.Height() )
{
rc.bottom = rc.top + pChild->MaxSize.cy;
}
}
else
{
ASSERT( FALSE );
}
pChild->SetRect(rc.TopLeft(), rc.BottomRight());
pChild->OnResized();
}
}
BOOL CPanel::AddChild(CPanel * pChild)
{
if (pChild->Parent != NULL)
{
BOOL bOk = pChild->Parent->RemoveChild(pChild);
if (bOk == FALSE)
{
return FALSE;
}
}
pChild->LeftOffset = pChild->left - this->left;
pChild->TopOffset = pChild->top - this->top;
pChild->RightOffset = this->right - pChild->right;
pChild->BottomOffset = this->bottom - pChild->bottom;
pChild->Parent = this;
Children.AddTail( pChild );
return TRUE;
}
BOOL CPanel::RemoveChild(CPanel * pChild)
{
POSITION pos = Children.Find(pChild);
if (pos == NULL)
{
return FALSE;
}
Children.RemoveAt(pos);
return TRUE;
}
BOOL CPanel::SetAnchor(UINT anchor)
{
if ((anchor & ANCHOR_VERTICALLY_CENTERED) <= 0 )
{
if ((anchor & ANCHOR_TOP) <= 0 )
{
if ((anchor & ANCHOR_BOTTOM) <= 0 )
{
anchor |= ANCHOR_TOP; }
}
}
if ((anchor & ANCHOR_HORIZONTALLY_CENTERED) <= 0 )
{
if ((anchor & ANCHOR_LEFT) <= 0 )
{
if ((anchor & ANCHOR_RIGHT) <= 0 )
{
anchor |= ANCHOR_LEFT; }
}
}
Anchor = anchor;
return TRUE;
}
BOOL CPanel::SetMinSize(CSize & size)
{
if (MaxSize.cx < size.cx)
{
return FALSE;
}
if (MaxSize.cy < size.cy)
{
return FALSE;
}
MinSize = size;
return TRUE;
}
BOOL CPanel::SetMaxSize(CSize & size)
{
if (MinSize.cx > size.cx)
{
return FALSE;
}
if (MinSize.cy > size.cy)
{
return FALSE;
}
MaxSize = size;
return TRUE;
}
BOOL CPanel::SetOffset(UINT anchor, int offset)
{
BOOL bRes = FALSE;
if (anchor & ANCHOR_TOP)
{
TopOffset = offset;
bRes = TRUE;
}
if (anchor & ANCHOR_LEFT)
{
LeftOffset = offset;
bRes = TRUE;
}
if (anchor & ANCHOR_BOTTOM)
{
BottomOffset = offset;
bRes = TRUE;
}
if (anchor & ANCHOR_RIGHT)
{
RightOffset = offset;
bRes = TRUE;
}
return bRes;
}
BOOL CPanel::SetVisible(BOOL bVisible)
{
m_bVisible = bVisible;
POSITION pos = Children.GetHeadPosition();
while( pos )
{
CPanel *pPanel = Children.GetNext( pos );
pPanel->SetVisible( bVisible );
}
return TRUE;
}
BOOL CPanel::GetVisible(BOOL &bVisible)
{
bVisible = m_bVisible;
return TRUE;
}
BOOL CPanel::IsVisible()
{
return m_bVisible;
}
CString CPanel::ToString()
{
CString sFormat(_T("Name(%s), Type(%s), Anchor(%d), Size(w:%d, h:%d), Area(l:%d, t:%d, r:%d, b:%d), MinSize(w:%d, h:%d), MaxSize(w:%d, h:%d), Parent(%s), ChildrenCount(%d)"));
CString sTo;
sTo.Format(sFormat, Name, GetTypeName(), Anchor, Width(), Height(), left, top, right, bottom, MinSize.cx, MinSize.cy, MaxSize.cx, MaxSize.cy, (Parent == NULL? _T("NULL") : Parent->Name), Children.GetCount());
return sTo;
}
CString CPanel::GetTypeName()
{
return _T("CPanel");
}
CWnd * CPanel::GetHookedWnd()
{
if (Parent != NULL)
return Parent->GetHookedWnd();
return NULL;
}
BOOL CPanel::PtInTriangle( CPoint point, UINT nEdge ) const
{
switch( nEdge )
{
case ANCHOR_TOPLEFT:
return PtInTriangle( point, CPoint(left,top), CPoint(right,top), CPoint(left,bottom) );
case ANCHOR_TOPRIGHT:
return PtInTriangle( point, CPoint(left,top), CPoint(right,top), CPoint(right,bottom) );
case ANCHOR_BOTTOMLEFT:
return PtInTriangle( point, CPoint(left,top), CPoint(left,bottom), CPoint(right,bottom) );
case ANCHOR_BOTTOMRIGHT:
return PtInTriangle( point, CPoint(left,bottom), CPoint(right,top), CPoint(right,bottom) );
default:
return FALSE;
}
}
static int GetSign( const CPoint &a, const CPoint &b, const CPoint &c )
{
return (a.x - c.x) * (b.y - c.y) - (b.x - c.x) * (a.y - c.y);
}
BOOL CPanel::PtInTriangle( CPoint point, CPoint v1, CPoint v2, CPoint v3 )
{
bool b1 = GetSign(point, v1, v2) < 0;
bool b2 = GetSign(point, v2, v3) < 0;
bool b3 = GetSign(point, v3, v1) < 0;
return ((b1 == b2) && (b2 == b3));
}
CRootPanel::CRootPanel() : CPanel()
{
m_pHookWnd = NULL;
}
CRootPanel::~CRootPanel()
{
}
CWnd * CRootPanel::GetHookedWnd()
{
return m_pHookWnd;
}
CString CRootPanel::GetTypeName()
{
return _T("CRootPanel");
}
CUIPanel::CUIPanel(const CRect * prc, UINT uID) : CPanel(prc)
{
m_uID = uID;
m_bOle = FALSE;
}
CUIPanel::~CUIPanel()
{
}
CString CUIPanel::GetTypeName()
{
return _T("CUIPanel");
}
BOOL CUIPanel::SetVisible(BOOL bVisible)
{
BOOL bRes = FALSE;
CPanel::SetVisible( bVisible );
CWnd *wnd = GetHookedWnd();
if( wnd )
{
CWnd *ctl = wnd->GetDlgItem( m_uID );
if( ctl )
bRes = ctl->ShowWindow( bVisible ? SW_SHOW : SW_HIDE );
}
return bRes;
}
BOOL CUIPanel::GetVisible(BOOL &bVisible)
{
bVisible = m_bVisible;
return TRUE;
}
BOOL CUIPanel::IsVisible()
{
return m_bVisible;
}
CVisualPanel::CVisualPanel() : CPanel()
{
m_bVisible = FALSE;
m_rcPrev.SetRect(0, 0, 0, 0);
}
CVisualPanel::CVisualPanel(const CRect * prc) : CPanel(prc)
{
m_bVisible = FALSE;
m_rcPrev.SetRect(this->left, this->top, this->right, this->bottom);
}
CVisualPanel::~CVisualPanel()
{
}
void CVisualPanel::Draw(CDC * pDC)
{
}
CString CVisualPanel::GetTypeName()
{
return _T("CVisualPanel");
}
void CVisualPanel::OnResized()
{
CWnd * pWnd = NULL;
if ((pWnd = GetHookedWnd()) != NULL)
{
pWnd->InvalidateRect( &m_rcPrev, FALSE );
pWnd->InvalidateRect( this, FALSE );
}
m_rcPrev.SetRect(this->left, this->top, this->right, this->bottom);
}
CGripperPanel::CGripperPanel() : CVisualPanel()
{
m_hTheme = NULL;
}
CGripperPanel::CGripperPanel(const CRect * prc) : CVisualPanel(prc)
{
m_hTheme = NULL;
}
CGripperPanel::~CGripperPanel()
{
if (m_hTheme != NULL)
{
(void)::CloseThemeData(m_hTheme);
m_hTheme = NULL;
}
}
void CGripperPanel::Draw(CDC * pDC)
{
int iPartId = SBP_SIZEBOX;
int iStateId = 5; LPCWSTR wClassName = L"SCROLLBAR";
HWND hwnd = NULL;
if (m_hTheme == NULL)
{
hwnd = GetHookedWnd()->GetSafeHwnd();
if (hwnd == NULL)
return;
m_hTheme = ::OpenThemeData(hwnd, wClassName);
}
BOOL bDrawStd = TRUE;
if (m_hTheme)
{
HRESULT lres = ::DrawThemeBackground(m_hTheme, pDC->m_hDC, iPartId, iStateId, this, this);
if (!SUCCEEDED(lres))
{
(void)::CloseThemeData(m_hTheme);
m_hTheme = NULL;
if( hwnd )
{
m_hTheme = ::OpenThemeData(hwnd, wClassName);
if( m_hTheme )
lres = ::DrawThemeBackground(m_hTheme, pDC->m_hDC, iPartId, iStateId, this, this);
}
}
if (SUCCEEDED(lres))
bDrawStd = FALSE;
}
if (bDrawStd)
(void)pDC->DrawFrameControl(this, DFC_SCROLL, DFCS_SCROLLSIZEGRIP );
}
CString CGripperPanel::GetTypeName()
{
return _T("CGripperPanel");
}
CSplitterGripperPanel::CSplitterGripperPanel(CWndResizer::SplitterOrientation type) : CVisualPanel()
{
m_OrienType = type;
}
CSplitterGripperPanel::~CSplitterGripperPanel()
{
}
void CSplitterGripperPanel::Draw(CDC * pDC)
{
CPen penDark(PS_SOLID, 1, ::GetSysColor(COLOR_3DSHADOW));
CPen penWhite(PS_SOLID, 1, ::GetSysColor(COLOR_3DHIGHLIGHT));
if (m_OrienType == CWndResizer::SPLIT_CONTAINER_H )
{
CPen * pOrigPen = pDC->SelectObject(&penWhite);
CRect rc(0, 0, 0, 0);
rc.SetRect(left + 1, top + 1, left + 3, top + 3);
while(rc.bottom <= bottom + 1)
{
pDC->Rectangle(&rc);
rc.OffsetRect(0, 4);
}
pDC->SelectObject(&penDark);
rc.SetRect(left, top, left + 2, top + 2);
while(rc.bottom <= bottom)
{
pDC->Rectangle(&rc);
rc.OffsetRect(0, 4);
}
pDC->SelectObject(pOrigPen);
}
else
{
CPen * pOrigPen = pDC->SelectObject(&penWhite);
CRect rc(0, 0, 0, 0);
rc.SetRect(left + 1, top + 1, left + 3, top + 3);
while(rc.right <= right + 1)
{
pDC->Rectangle(&rc);
rc.OffsetRect(4, 0);
}
pDC->SelectObject(&penDark);
rc.SetRect(left, top, left + 2, top + 2);
while(rc.right <= right)
{
pDC->Rectangle(&rc);
rc.OffsetRect(4, 0);
}
pDC->SelectObject(pOrigPen);
}
}
CString CSplitterGripperPanel::GetTypeName()
{
return _T("CSplitterGripperPanel");
}
CSpitterPanel::CSpitterPanel(const CRect * prc, CWndResizer::SplitterOrientation type) : CPanel(prc)
{
m_OrienType = type;
m_pGrippePanel = NULL;
if (m_pGrippePanel == NULL)
{
m_pGrippePanel = new CSplitterGripperPanel(type);
if (m_OrienType == CWndResizer::SPLIT_CONTAINER_H )
{
m_pGrippePanel->SetRect(0, 0, 3, 12);
}
else
{
m_pGrippePanel->SetRect(0, 0, 12, 3);
}
m_pGrippePanel->SetAnchor ( ANCHOR_HORIZONTALLY_CENTERED | ANCHOR_VERTICALLY_CENTERED );
m_pGrippePanel->SetMinSize(CSize(2,2));
BOOL bOk = AddChild(m_pGrippePanel);
ASSERT( bOk);
}
}
CSpitterPanel::CSpitterPanel(CWndResizer::SplitterOrientation type) : CPanel()
{
m_OrienType = type;
m_pGrippePanel = NULL;
}
CSpitterPanel::~CSpitterPanel()
{
}
CString CSpitterPanel::GetTypeName()
{
return _T("CSpitterPanel");
}
#ifdef USE_SPLIT_PANEL
CSplitPanel::CSplitPanel(CPanel * pPanel) : CPanel(pPanel)
{
pPanel->LeftOffset = 0;
pPanel->TopOffset = 0;
pPanel->RightOffset = 0;
pPanel->BottomOffset = 0;
pPanel->Anchor = ANCHOR_ALL;
Name = pPanel->Name;
pPanel->Name = _T("");
m_pOriginalPanel = pPanel;
MaxSize = pPanel->MaxSize;
MinSize = pPanel->MinSize;
Children.AddTail( pPanel );
}
CSplitPanel::~CSplitPanel()
{
}
BOOL CSplitPanel::SetAnchor(UINT anchor)
{
return FALSE;
}
BOOL CSplitPanel::AddChild(CPanel * prc)
{
return m_pOriginalPanel->AddChild(prc);
}
BOOL CSplitPanel::RemoveChild(CPanel * prc)
{
return m_pOriginalPanel->RemoveChild(prc);
}
CString CSplitPanel::GetTypeName()
{
return _T("CSplitPanel");
}
BOOL CSplitPanel::SetMinSize(CSize & size)
{
if( !CPanel::SetMinSize( size ) )
return FALSE;
if( m_pOriginalPanel )
return m_pOriginalPanel->SetMinSize( size );
return TRUE;
}
BOOL CSplitPanel::SetMaxSize(CSize & size)
{
if( !CPanel::SetMaxSize( size ) )
return FALSE;
if( m_pOriginalPanel )
return m_pOriginalPanel->SetMaxSize( size );
return TRUE;
}
#endif
CSplitContainer::CSplitContainer(CSplitPanel * pPanelA, CSplitPanel * pPanelB, CWndResizer::SplitterOrientation type) : CPanel()
{
m_IsSplitterFixed = FALSE;
m_FixedPanel = 0;
m_pPanelA = NULL;
m_pPanelB = NULL;
m_pSplitter = NULL;
m_Orientation = type;
m_pPanelA = pPanelA;
m_pPanelB = pPanelB;
UnionRect(m_pPanelA, m_pPanelB);
CRect rc(0, 0, 0, 0);
GetSplitArea(&rc);
m_pSplitter = new CSpitterPanel(&rc, type);
m_pSplitter->m_pGrippePanel->m_bVisible = FALSE;
if (m_Orientation == CWndResizer::SPLIT_CONTAINER_H)
{
m_pPanelA->Anchor = (ANCHOR_LEFT | ANCHOR_TOP | ANCHOR_BOTTOM);
m_pPanelB->Anchor = (ANCHOR_RIGHT | ANCHOR_TOP | ANCHOR_BOTTOM);
}
else
{
m_pPanelA->Anchor = (ANCHOR_LEFT | ANCHOR_TOP | ANCHOR_RIGHT);
m_pPanelB->Anchor = (ANCHOR_LEFT | ANCHOR_BOTTOM | ANCHOR_RIGHT);
}
m_nSplitterSize = GetSplitterSize(m_pPanelA, m_pPanelB);
BOOL bOk = AddChild(m_pPanelA);
ASSERT( bOk);
bOk = AddChild(m_pSplitter);
ASSERT( bOk);
bOk = AddChild(m_pPanelB);
ASSERT( bOk);
UpdateRatio();
}
CSplitContainer::~CSplitContainer()
{
}
void CSplitContainer::OnResized()
{
CPanel::OnResized();
BOOL bShowA = TRUE;
BOOL bShowB = TRUE;
BOOL bShowS = TRUE;
if (m_Orientation == CWndResizer::SPLIT_CONTAINER_H)
{
if (Width() < MinSize.cx)
return;
if (m_FixedPanel == CWndResizer::FIXED_LEFT ) {
m_pPanelB->left = m_pPanelA->right + m_nSplitterSize;
if (m_pPanelB->MinSize.cx > m_pPanelB->Width() )
{
m_pPanelB->left = m_pPanelB->right - m_pPanelB->MinSize.cx;
m_pPanelA->right = m_pPanelB->left - m_nSplitterSize;
}
}
else if (m_FixedPanel == CWndResizer::FIXED_RIGHT ) {
m_pPanelA->right = m_pPanelB->left - m_nSplitterSize;
if (m_pPanelA->MinSize.cx > m_pPanelA->Width() )
{
m_pPanelA->right = m_pPanelA->left + m_pPanelA->MinSize.cx;
m_pPanelB->left = m_pPanelA->right + m_nSplitterSize;
}
}
else if (m_FixedPanel == CWndResizer::FIXED_LEFT_HIDDEN ) {
m_pPanelB->left = m_pPanelA->left;
m_pPanelA->right = m_pPanelA->left;
bShowS = FALSE;
}
else if (m_FixedPanel == CWndResizer::FIXED_RIGHT_HIDDEN ) {
m_pPanelA->right = m_pPanelB->right;
m_pPanelB->left = m_pPanelB->right;
bShowS = FALSE;
}
else
{
m_pPanelA->right = (LONG) ((double)m_pPanelA->left + ((double)this->Width() * m_nRatio));
if (m_pPanelA->MinSize.cx > m_pPanelA->Width() )
{
m_pPanelA->right = m_pPanelA->left + m_pPanelA->MinSize.cx;
}
m_pPanelB->left = m_pPanelA->right + m_nSplitterSize;
if (m_pPanelB->MinSize.cx > m_pPanelB->Width() )
{
m_pPanelB->left = m_pPanelB->right - m_pPanelB->MinSize.cx;
m_pPanelA->right = m_pPanelB->left - m_nSplitterSize;
}
}
if (m_pPanelA->Width() <= 2)
bShowA = FALSE;
if (m_pPanelB->Width() <= 2)
bShowB = FALSE;
}
else
{
if (Height() < MinSize.cy)
{
return;
}
if (m_FixedPanel == CWndResizer::FIXED_TOP ) {
m_pPanelB->top = m_pPanelA->bottom + m_nSplitterSize;
if (m_pPanelB->MinSize.cy > m_pPanelB->Height() )
{
m_pPanelB->top = m_pPanelB->bottom - m_pPanelB->MinSize.cy;
m_pPanelA->bottom = m_pPanelB->top - m_nSplitterSize;
}
}
else if (m_FixedPanel == CWndResizer::FIXED_BOTTOM ) {
m_pPanelA->bottom = m_pPanelB->top - m_nSplitterSize;
if (m_pPanelA->MinSize.cy > m_pPanelA->Height() )
{
m_pPanelA->bottom = m_pPanelA->top + m_pPanelA->MinSize.cy;
m_pPanelB->top = m_pPanelA->bottom + m_nSplitterSize;
}
}
else if (m_FixedPanel == CWndResizer::FIXED_TOP_HIDDEN ) {
m_pPanelB->top = m_pPanelA->top;
bShowA = FALSE;
bShowS = FALSE;
}
else if (m_FixedPanel == CWndResizer::FIXED_BOTTOM_HIDDEN ) {
m_pPanelA->bottom = m_pPanelB->bottom;
bShowS = FALSE;
bShowB = FALSE;
}
else
{
m_pPanelA->bottom = (LONG) ((double)m_pPanelA->top + ((double)this->Height() * m_nRatio));
if (m_pPanelA->MinSize.cy > m_pPanelA->Height() )
{
m_pPanelA->bottom = m_pPanelA->top + m_pPanelA->MinSize.cy;
}
m_pPanelB->top = m_pPanelA->bottom + m_nSplitterSize;
if (m_pPanelB->MinSize.cy > m_pPanelB->Height() )
{
m_pPanelB->top = m_pPanelB->bottom - m_pPanelB->MinSize.cy;
m_pPanelA->bottom = m_pPanelB->top - m_nSplitterSize;
}
}
if (m_pPanelA->Height() <= 2)
bShowA = FALSE;
if (m_pPanelB->Height() <= 2)
bShowB = FALSE;
}
#if 0
GetSplitArea(m_pSplitter);
m_pPanelA->OnResized();
m_pPanelB->OnResized();
m_pSplitter->OnResized();
#else
m_pPanelA->SetVisible( bShowA );
if( bShowA )
m_pPanelA->OnResized();
m_pPanelB->SetVisible( bShowB );
if( bShowB )
m_pPanelB->OnResized();
if( bShowS )
{
if( !bShowA )
m_nRatio = 0;
else if( !bShowB )
m_nRatio = 100;
GetSplitArea(m_pSplitter);
m_pSplitter->SetVisible( !m_IsSplitterFixed );
m_pSplitter->OnResized();
}
else
m_pSplitter->SetVisible( FALSE );
#endif
}
void CSplitContainer::SetSplitterPosition(int leftOfSplitter)
{
short nFixedPanel = m_FixedPanel;
m_FixedPanel = 0;
if (m_Orientation == CWndResizer::SPLIT_CONTAINER_H )
{
m_pPanelA->right = leftOfSplitter;
m_pPanelB->left = m_pPanelA->right + m_nSplitterSize;
}
else
{
m_pPanelA->bottom = leftOfSplitter;
m_pPanelB->top = m_pPanelA->bottom + m_nSplitterSize;
}
UpdateRatio();
OnResized();
UpdateRatio();
m_FixedPanel = nFixedPanel;
}
int CSplitContainer::GetSplitterPosition()
{
if (m_Orientation == CWndResizer::SPLIT_CONTAINER_H )
return m_pPanelA->right;
return m_pPanelA->bottom;
}
BOOL CSplitContainer::AddChild(CPanel * prc)
{
if (Children.GetCount() == 3)
return FALSE;
return CPanel::AddChild(prc);
}
BOOL CSplitContainer::RemoveChild(CPanel * prc)
{
return FALSE; }
void CSplitContainer::GetSplitArea(CRect * pSplitterPanel)
{
if (m_Orientation == CWndResizer::SPLIT_CONTAINER_H)
{
pSplitterPanel->left = m_pPanelA->right;
pSplitterPanel->top = this->top;
pSplitterPanel->right = m_pPanelB->left;
pSplitterPanel->bottom = this->bottom;
}
else {
pSplitterPanel->left = this->left;
pSplitterPanel->top = m_pPanelA->bottom;
pSplitterPanel->right = this->right;
pSplitterPanel->bottom = m_pPanelB->top;
}
}
int CSplitContainer::GetSplitterSize(CPanel * m_pPanelA, CPanel * m_pPanelB)
{
if (m_Orientation == CWndResizer::SPLIT_CONTAINER_H)
{
int nWidth = m_pPanelB->left - m_pPanelA->right;
return nWidth;
}
else {
int nHeight = m_pPanelB->top - m_pPanelA->bottom;
return nHeight;
}
}
void CSplitContainer::UpdateRatio()
{
if (m_Orientation == CWndResizer::SPLIT_CONTAINER_H )
{
m_nRatio = (double)m_pPanelA->Width() / (double)this->Width();
}
else
{
m_nRatio = (double)m_pPanelA->Height() / (double)this->Height();
}
}
CSplitContainer * CSplitContainer::Create(CPanel * pPanelA, CPanel * pPanelB)
{
#ifdef USE_SPLIT_PANEL
CSplitPanel * pSplitPanelA = dynamic_cast<CSplitPanel *>( pPanelA );
if (pSplitPanelA != NULL)
{
return NULL; }
CSplitPanel * pSplitPanelB = dynamic_cast<CSplitPanel *>( pPanelB );
if (pSplitPanelB != NULL)
{
return NULL; }
#endif
CRect rcDest(0, 0, 0, 0);
CWndResizer::SplitterOrientation orien = CWndResizer::SPLIT_CONTAINER_H;
if (::IntersectRect(&rcDest, pPanelA, pPanelB) == TRUE) {
return NULL;
}
if (pPanelA->right < pPanelB->left)
{
orien = CWndResizer::SPLIT_CONTAINER_H;
}
else if (pPanelA->bottom < pPanelB->top)
{
orien = CWndResizer::SPLIT_CONTAINER_V;
}
else
{
return NULL;
}
#ifdef USE_SPLIT_PANEL
if (pPanelA->Parent != NULL)
{
if (pPanelA->Parent->RemoveChild( pPanelA ) == FALSE)
{
return NULL;
}
}
if (pPanelB->Parent != NULL)
{
if (pPanelB->Parent->RemoveChild( pPanelB ) == FALSE)
{
return NULL;
}
}
#endif
CSplitContainer * pSpliter = new CSplitContainer(pPanelA, pPanelB, orien);
return pSpliter;
}
CString CSplitContainer::GetTypeName()
{
return _T("CSplitContainer");
}
void CSplitContainer::SetFixedPanel(short nFixedPanel )
{
m_FixedPanel = nFixedPanel;
}
short CSplitContainer::GetFixedPanel()
{
return m_FixedPanel;
}
void CSplitContainer::SetIsSplitterFixed(BOOL bFixed)
{
m_IsSplitterFixed = bFixed;
}
BOOL CSplitContainer::GetIsSplitterFixed()
{
return m_IsSplitterFixed;
}
void CSplitContainer::SetShowSplitterGrip(BOOL bShow)
{
m_pSplitter->m_pGrippePanel->m_bVisible = bShow;
}
BOOL CSplitContainer::GetShowSplitterGrip()
{
return m_pSplitter->m_pGrippePanel->m_bVisible;
}
CFlowLayoutPanel::CFlowLayoutPanel() : CPanel()
{
m_nItemSpacingX = 0;
m_nItemSpacingY = 0;
m_nFlowDirection = CWndResizer::LEFT_TO_RIGHT;
}
CFlowLayoutPanel::CFlowLayoutPanel(const CRect * prc) : CPanel(prc)
{
m_nItemSpacingX = 0;
m_nItemSpacingY = 0;
m_nFlowDirection = CWndResizer::LEFT_TO_RIGHT;
}
CFlowLayoutPanel::~CFlowLayoutPanel()
{
}
void CFlowLayoutPanel::OnResized()
{
int max = 0; int x = left;
int y = top;
POSITION pos = Children.GetHeadPosition();
if (pos != NULL)
{
CPanel * pPanel = Children.GetNext(pos);
pPanel->MoveToXY(x, y);
pPanel->OnResized();
if (m_nFlowDirection == CWndResizer::LEFT_TO_RIGHT)
{
x += pPanel->Width() + m_nItemSpacingX;
max = (pPanel->Height() > max ? pPanel->Height() : max);
}
else
{
y += pPanel->Height() + m_nItemSpacingY;
max = (pPanel->Width() > max ? pPanel->Width() : max);
}
}
if (m_nFlowDirection == CWndResizer::LEFT_TO_RIGHT)
{
while(pos != NULL)
{
CPanel * pPanel = Children.GetNext(pos);
if (x + pPanel->Width() > right)
{
x = left;
y += (max + m_nItemSpacingY);
max = 0;
}
pPanel->MoveToXY(x, y);
pPanel->OnResized();
x += pPanel->Width() + m_nItemSpacingX;
max = (pPanel->Height() > max ? pPanel->Height() : max);
}
}
else
{
while(pos != NULL)
{
CPanel * pPanel = Children.GetNext(pos);
if (y + pPanel->Height() > bottom)
{
x += (max + m_nItemSpacingX);
y = top;
max = 0;
}
pPanel->MoveToXY(x, y);
pPanel->OnResized();
y += pPanel->Height() + m_nItemSpacingY;
max = (pPanel->Width() > max ? pPanel->Width() : max);
}
}
}
CString CFlowLayoutPanel::GetTypeName()
{
return _T("CFlowLayoutPanel");
}
void CFlowLayoutPanel::SetFlowDirection(CWndResizer::FlowDirection direction)
{
m_nFlowDirection = direction;
}
CWndResizer::FlowDirection CFlowLayoutPanel::GetFlowDirection()
{
return m_nFlowDirection;
}
void CFlowLayoutPanel::SetItemSpacingX(int nSpace)
{
m_nItemSpacingX = nSpace;
}
int CFlowLayoutPanel::GetItemSpacingX()
{
return m_nItemSpacingX;
}
void CFlowLayoutPanel::SetItemSpacingY(int nSpace)
{
m_nItemSpacingY = nSpace;
}
int CFlowLayoutPanel::GetItemSpacingY()
{
return m_nItemSpacingY;
}
|
|
|
|
|
Here is test dialog class (Example 11)
Header file
#pragma once
#include "WndResizer.h"
class CExample11Dlg : public CDialog
{
DECLARE_DYNAMIC(CExample11Dlg)
public:
CExample11Dlg(CWnd* pParent = NULL); virtual ~CExample11Dlg();
enum { IDD = IDD_EX11_DLG };
CWndResizer m_resizer;
protected:
virtual void DoDataExchange(CDataExchange* pDX);
DECLARE_MESSAGE_MAP()
public:
virtual BOOL OnInitDialog();
afx_msg void OnShowOptionsCheck();
afx_msg void OnHideTopPanelCheck();
afx_msg void OnHideBottomPanelCheck();
};
Implementation file (CPP)
#include "stdafx.h"
#include "WndResizerApp.h"
#include "Example11Dlg.h"
IMPLEMENT_DYNAMIC(CExample11Dlg, CDialog)
CExample11Dlg::CExample11Dlg(CWnd* pParent )
: CDialog(CExample11Dlg::IDD, pParent)
{
}
CExample11Dlg::~CExample11Dlg()
{
}
void CExample11Dlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CExample11Dlg, CDialog)
ON_BN_CLICKED(IDC_OPTIONS_CHECK, OnShowOptionsCheck)
ON_BN_CLICKED(IDC_HIDE_TOP_CHECK, OnHideTopPanelCheck)
ON_BN_CLICKED(IDC_HIDE_BOTTOM_CHECK, OnHideBottomPanelCheck)
END_MESSAGE_MAP()
BOOL CExample11Dlg::OnInitDialog()
{
CDialog::OnInitDialog();
m_resizer.Hook( this );
m_resizer.SetAnchor( IDC_TOPLABEL, ANCHOR_TOP | ANCHOR_HORIZONTALLY );
#if 1
m_resizer.CreateSplitContainer( _T("InputOutputSplitter"), IDC_INPUT_EDIT, IDC_OUTPUT_EDIT );
m_resizer.SetShowSplitterGrip( _T("InputOutputSplitter"), TRUE );
m_resizer.SetAnchor( _T("InputOutputSplitter"), ANCHOR_ALL );
m_resizer.SetParent( IDC_INPUT_LABEL, IDC_INPUT_EDIT );
m_resizer.SetAnchor( IDC_INPUT_LABEL, ANCHOR_LEFT | ANCHOR_TOP );
m_resizer.SetParent( IDC_INPUT_CLEAR_BUTTON, IDC_INPUT_EDIT );
m_resizer.SetAnchor( IDC_INPUT_CLEAR_BUTTON, ANCHOR_RIGHT | ANCHOR_TOP );
m_resizer.SetMinimumSize( IDC_INPUT_EDIT, CSize(0, 0) );
#else
const UINT inputIds[] = { IDC_INPUT_EDIT, IDC_INPUT_LABEL, IDC_INPUT_CLEAR_BUTTON, 0 };
m_resizer.CreatePanel( _T("InputPanel"), inputIds, TRUE );
m_resizer.SetAnchor( IDC_INPUT_EDIT, ANCHOR_ALL );
m_resizer.SetAnchor( IDC_INPUT_LABEL, ANCHOR_LEFT | ANCHOR_TOP );
m_resizer.SetAnchor( IDC_INPUT_CLEAR_BUTTON, ANCHOR_RIGHT | ANCHOR_TOP );
m_resizer.SetMinimumSize( IDC_INPUT_EDIT, CSize(0, 0) );
m_resizer.SetMinimumSize( _T("InputPanel"), CSize(0, 0) );
m_resizer.CreateSplitContainer( _T("InputOutputSplitter"), _T("InputPanel"), IDC_OUTPUT_EDIT );
m_resizer.SetShowSplitterGrip( _T("InputOutputSplitter"), TRUE );
m_resizer.SetAnchor( _T("InputOutputSplitter"), ANCHOR_ALL );
#endif
m_resizer.SetParent( IDC_OUTPUT_LABEL, IDC_OUTPUT_EDIT );
m_resizer.SetAnchor( IDC_OUTPUT_LABEL, ANCHOR_LEFT | ANCHOR_TOP );
m_resizer.SetParent( IDC_OUTPUT_CLEAR_BUTTON, IDC_OUTPUT_EDIT );
m_resizer.SetAnchor( IDC_OUTPUT_CLEAR_BUTTON, ANCHOR_RIGHT | ANCHOR_TOP );
m_resizer.SetMinimumSize( IDC_OUTPUT_EDIT, CSize(0, 0) );
const UINT options_panel_ids[] = { IDC_ICON_STATIC, IDC_HIDE_TOP_CHECK, IDC_HIDE_BOTTOM_CHECK, 0 };
m_resizer.CreatePanel( _T("OptionsPanel"), options_panel_ids, TRUE );
m_resizer.SetAnchor( _T("OptionsPanel"), ANCHOR_BOTTOMLEFT );
m_resizer.CreateSplitContainer( _T("MainSplitter"), _T("InputOutputSplitter"), _T("OptionsPanel") );
m_resizer.SetAnchor( _T("MainSplitter"), ANCHOR_ALL );
m_resizer.SetIsSplitterFixed( _T("MainSplitter"), TRUE );
m_resizer.SetFixedPanel( _T("MainSplitter"), CWndResizer::FIXED_BOTTOM );
m_resizer.SetAnchor( IDC_OPTIONS_CHECK, ANCHOR_BOTTOMLEFT );
m_resizer.SetAnchor( IDOK, ANCHOR_BOTTOMRIGHT );
m_resizer.SetAnchor( IDCANCEL, ANCHOR_BOTTOMRIGHT );
m_resizer.SetShowResizeGrip();
CRect rcMin;
GetClientRect( &rcMin );
m_resizer.SetMinimumSize( CWndResizer::RootPanelName, CSize(rcMin.Width(), rcMin.Height()) );
CheckDlgButton( IDC_OPTIONS_CHECK, BST_CHECKED );
m_resizer.InvokeOnResized();
return TRUE; }
void CExample11Dlg::OnShowOptionsCheck()
{
if( IsDlgButtonChecked( IDC_OPTIONS_CHECK ) )
m_resizer.SetFixedPanel( _T("MainSplitter"), CWndResizer::FIXED_BOTTOM );
else
m_resizer.SetFixedPanel( _T("MainSplitter"), CWndResizer::FIXED_BOTTOM_HIDDEN );
m_resizer.InvokeOnResized();
}
void CExample11Dlg::OnHideTopPanelCheck()
{
if( IsDlgButtonChecked( IDC_HIDE_TOP_CHECK ) )
{
m_resizer.SetFixedPanel( _T("InputOutputSplitter"), CWndResizer::FIXED_TOP_HIDDEN );
CheckDlgButton( IDC_HIDE_BOTTOM_CHECK, BST_UNCHECKED );
}
else
m_resizer.SetFixedPanel( _T("InputOutputSplitter"), 0 );
m_resizer.InvokeOnResized();
}
void CExample11Dlg::OnHideBottomPanelCheck()
{
if( IsDlgButtonChecked( IDC_HIDE_BOTTOM_CHECK ) )
{
m_resizer.SetFixedPanel( _T("InputOutputSplitter"), CWndResizer::FIXED_BOTTOM_HIDDEN );
CheckDlgButton( IDC_HIDE_TOP_CHECK, BST_UNCHECKED );
}
else
m_resizer.SetFixedPanel( _T("InputOutputSplitter"), 0 );
m_resizer.InvokeOnResized();
}
Control definitions:
#define IDD_EX11_DLG 138
#define IDC_HIDE_TOP_CHECK 1057
#define IDC_TOPLABEL 1058
#define IDC_OPTIONS_CHECK 1059
#define IDC_BOTTOM_HIDE_CHECK 1060
#define IDC_ICON_STATIC 1061
#define IDC_HIDE_BOTTOM_CHECK 1062
#define IDC_OUTPUT_EDIT 1331
#define IDC_INPUT_EDIT 1332
#define IDC_INPUT_LABEL 1351
#define IDC_OUTPUT_LABEL 1352
#define IDC_OUTPUT_CLEAR_BUTTON 1353
#define IDC_INPUT_CLEAR_BUTTON 1354
And Dialog template:
IDD_EX11_DLG DIALOGEX 0, 0, 276, 184
STYLE DS_SETFONT | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME
CAPTION "Example 11: Splitter and hiding"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
DEFPUSHBUTTON "OK",IDOK,167,163,50,14
PUSHBUTTON "Cancel",IDCANCEL,219,163,50,14
LTEXT "This example shows automatic hiding of splitter and maximizing one of the panels in splitter",IDC_TOPLABEL,7,7,262,19
LTEXT "Input data:",IDC_INPUT_LABEL,7,31,38,8
EDITTEXT IDC_INPUT_EDIT,7,40,262,42,ES_MULTILINE | WS_VSCROLL
PUSHBUTTON "x",IDC_INPUT_CLEAR_BUTTON,257,30,12,10,BS_BOTTOM | BS_FLAT
LTEXT "Output data:",IDC_OUTPUT_LABEL,7,84,43,8
EDITTEXT IDC_OUTPUT_EDIT,7,93,262,42,ES_MULTILINE | WS_VSCROLL
PUSHBUTTON "x",IDC_OUTPUT_CLEAR_BUTTON,257,83,12,10,BS_BOTTOM | BS_FLAT
ICON IDR_MAINFRAME,IDC_ICON_STATIC,14,140,21,20
CONTROL "Show options",IDC_OPTIONS_CHECK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,167,59,10
CONTROL "Hide top panel",IDC_HIDE_TOP_CHECK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,51,140,62,10
CONTROL "Hide bottom panel",IDC_HIDE_BOTTOM_CHECK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,51,151,74,10
END
Michał
|
|
|
|
|