Advanced MFC Programming

Advanced MFC Programming Advanced MFC Programming

math.hcmuns.edu.vn
from math.hcmuns.edu.vn More from this publisher
11.04.2014 Views

Chapter 3. Splitter Window Split box Split box Figure 3-3. Double clicking on any of the split boxes will divide the window into panes dynamically This behavior could be customized. For example, sometimes by double clicking on the split bar, we want to resize the two panes instead of deleting one of them. This feature gives the user much convenience for changing the size of each pane bit by bit. Split bar Figure 3-4. Double clicking on the split bar will delete one of the two panes divided by the split bar Splitter Window Layout We need to override the following two member functions of class CSplitterWnd in order to implement this feature: CSplitterWnd::DeleteRow(…) and CSplitterWnd::DeleteColumn(…). When the user double clicks on the split bar, one of the two functions will be called to delete a row or column dynamically. In order to customize this behavior, after the split bar is clicked, we can first change the size of each pane, then judge if the size of one pane is smaller than its minimum size. If so, we call the default implementation of the corresponding function to delete one row or column. To change a pane’s size, we need to call function CSplitterWnd::SetColumnInfo(…) and CSplitterWnd::SetRowInfo(…). The current size of a pane could be obtained by their counterpart functions CSplitterWnd::GetColumnInfo(…) and CSplitterWnd::GetRowInfo(…). The following shows the formats of the above four functions: void CSplitterWnd::SetColumnInfo(int col, int cxIdeal, int cxMin); void CSplitterWnd::SetRowInfo(int row, int cyIdeal, int cyMin); void CSplitterWnd::GetColumnInfo(int col, int& cxCur, int& cxMin); void CSplitterWnd::GetRowInfo(int row, int& cyCur, int& cyMin); 62

Chapter 3. Splitter Window In the above functions, parameters row and col are used to identify a pane with specified row and column indices, cyIdeal and cxIdeal are the ideal size of a pane, cyMin and cxMin indicate minimum size of it. When the splitter window is being displayed, each pane’s dimension is decided from its ideal size. According to the current size of the frame window, some panes may be set to their ideal sizes, but some may not (This depends on how much space is left for that pane). In any case, a pane’s actual size should not be smaller than its minimum size. This is why we need both ideal size and minimum size to set a row or column’s dimension. The number of rows and columns a splitter window currently has can be obtained by calling other two member functions of CSplitterWnd: int CSplitterWnd::GetRowCount(); int CSplitterWnd::GetColumnCount(); After we call function CSplitterWnd::SetColumnInfo(…) or CSplitterWnd::SetRowInfo(…), the old layout will not change until we call function CSplitterWnd::RecalcLayout() to update the splitter window. The system will re-calculate the layout for each pane according to their new sizes (both ideal size and minimum size), and the split bar will be moved to a new position according to the new layout. Overriding CSplitterWnd::DeleteRow(…) and CSplitterWnd:: DeleteColumn(…) Sample 3.3\Spw is based on sample 3.2\Spw. In the new sample, the behavior of the split bar is modified: if the user double clicks on it, it will move a small step downward (for horizontal split bar) or rightward (for vertical split bar). A pane will be deleted after it reaches its minimum size. In the sample application, first a new class MCSplitterWnd is derived from class CSplitterWnd: class MCSplitterWnd : public CSplitterWnd { public: void DeleteRow(int); void DeleteColumn(int); }; The class does nothing but overriding two functions. The implementation of function MCSplitterWnd ::DeleteRow(…) is listed as follows: void MCSplitterWnd::DeleteRow(int rowDelete) { int nNumRows; nNumRows=GetRowCount(); if(nNumRows < 2) { CSplitterWnd::DeleteRow(rowDelete); } else { int nCyCur, nCyMin; GetRowInfo(0, nCyCur, nCyMin); nCyCur+=ONE_STEP_MOVE; SetRowInfo(0, nCyCur, nCyMin); GetRowInfo(1, nCyCur, nCyMin); nCyCur-=ONE_STEP_MOVE; if(nCyCur < nCyMin) { CSplitterWnd::DeleteRow(rowDelete); } else { SetRowInfo(1, nCyCur, nCyMin); 63

Chapter 3. Splitter Window<br />

In the above functions, parameters row and col are used to identify a pane with specified row and<br />

column indices, cyIdeal and cxIdeal are the ideal size of a pane, cyMin and cxMin indicate minimum size<br />

of it.<br />

When the splitter window is being displayed, each pane’s dimension is decided from its ideal size.<br />

According to the current size of the frame window, some panes may be set to their ideal sizes, but some<br />

may not (This depends on how much space is left for that pane). In any case, a pane’s actual size should not<br />

be smaller than its minimum size. This is why we need both ideal size and minimum size to set a row or<br />

column’s dimension.<br />

The number of rows and columns a splitter window currently has can be obtained by calling other two<br />

member functions of CSplitterWnd:<br />

int CSplitterWnd::GetRowCount();<br />

int CSplitterWnd::GetColumnCount();<br />

After we call function CSplitterWnd::SetColumnInfo(…) or CSplitterWnd::SetRowInfo(…), the old<br />

layout will not change until we call function CSplitterWnd::RecalcLayout() to update the splitter<br />

window. The system will re-calculate the layout for each pane according to their new sizes (both ideal size<br />

and minimum size), and the split bar will be moved to a new position according to the new layout.<br />

Overriding CSplitterWnd::DeleteRow(…) and CSplitterWnd::<br />

DeleteColumn(…)<br />

Sample 3.3\Spw is based on sample 3.2\Spw. In the new sample, the behavior of the split bar is<br />

modified: if the user double clicks on it, it will move a small step downward (for horizontal split bar) or<br />

rightward (for vertical split bar). A pane will be deleted after it reaches its minimum size.<br />

In the sample application, first a new class MCSplitterWnd is derived from class CSplitterWnd:<br />

class MCSplitterWnd : public CSplitterWnd<br />

{<br />

public:<br />

void DeleteRow(int);<br />

void DeleteColumn(int);<br />

};<br />

The class does nothing but overriding two functions. The implementation of function MCSplitterWnd<br />

::DeleteRow(…) is listed as follows:<br />

void MCSplitterWnd::DeleteRow(int rowDelete)<br />

{<br />

int nNumRows;<br />

nNumRows=GetRowCount();<br />

if(nNumRows < 2)<br />

{<br />

CSplitterWnd::DeleteRow(rowDelete);<br />

}<br />

else<br />

{<br />

int nCyCur, nCyMin;<br />

GetRowInfo(0, nCyCur, nCyMin);<br />

nCyCur+=ONE_STEP_MOVE;<br />

SetRowInfo(0, nCyCur, nCyMin);<br />

GetRowInfo(1, nCyCur, nCyMin);<br />

nCyCur-=ONE_STEP_MOVE;<br />

if(nCyCur < nCyMin)<br />

{<br />

CSplitterWnd::DeleteRow(rowDelete);<br />

}<br />

else<br />

{<br />

SetRowInfo(1, nCyCur, nCyMin);<br />

63

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!