Advanced MFC Programming
Advanced MFC Programming Advanced MFC Programming
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
- Page 27 and 28: Chapter 1. Tool Bar and Dialog Bar
- Page 29 and 30: Chapter 1. Tool Bar and Dialog Bar
- Page 31 and 32: Chapter 1. Tool Bar and Dialog Bar
- Page 33 and 34: Chapter 1. Tool Bar and Dialog Bar
- Page 35 and 36: Chapter 1. Tool Bar and Dialog Bar
- Page 37 and 38: Chapter 1. Tool Bar and Dialog Bar
- Page 39 and 40: Chapter 1. Tool Bar and Dialog Bar
- Page 41 and 42: Chapter 1. Tool Bar and Dialog Bar
- Page 43 and 44: Chapter 1. Tool Bar and Dialog Bar
- Page 45 and 46: Chapter 1. Tool Bar and Dialog Bar
- Page 47 and 48: Chapter 1. Tool Bar and Dialog Bar
- Page 49 and 50: Chapter 2. Menu Chapter 2 Menu Menu
- Page 51 and 52: Chapter 2. Menu ON_COMMAND(ID_EDIT_
- Page 53 and 54: Chapter 2. Menu “clipboard”. We
- Page 55 and 56: Chapter 2. Menu Using Class CMenu W
- Page 57 and 58: Chapter 2. Menu } After implementin
- Page 59 and 60: Chapter 2. Menu ); UINT nPosition,
- Page 61 and 62: Chapter 2. Menu void CMenuDoc::OnEd
- Page 63 and 64: Chapter 2. Menu } In the sample, bi
- Page 65 and 66: Chapter 2. Menu Message Mapping for
- Page 67 and 68: Chapter 2. Menu We can implement bi
- Page 69 and 70: Chapter 2. Menu CDC *ptrDC; CDC dcM
- Page 71 and 72: Chapter 2. Menu Because the popup m
- Page 73 and 74: Chapter 3. Splitter Window Chapter
- Page 75 and 76: Chapter 3. Splitter Window function
- Page 77: Chapter 3. Splitter Window BOOL CSp
- Page 81 and 82: Chapter 3. Splitter Window Sample S
- Page 83 and 84: Chapter 3. Splitter Window WM_LBUTT
- Page 85 and 86: Chapter 4. Button Chapter 4 Buttons
- Page 87 and 88: Chapter 4. Button Use string text a
- Page 89 and 90: Chapter 4. Button function, first t
- Page 91 and 92: Chapter 4. Button Now we can remove
- Page 93 and 94: Chapter 4. Button } ( m_bBmpCheck ?
- Page 95 and 96: Chapter 4. Button using bit-wise AN
- Page 97 and 98: Chapter 4. Button Overriding Functi
- Page 99 and 100: Chapter 4. Button …… First pBit
- Page 101 and 102: Chapter 4. Button Using Class MCBit
- Page 103 and 104: Chapter 4. Button The button’s ID
- Page 105 and 106: Chapter 4. Button However, since me
- Page 107 and 108: Chapter 4. Button Here, we use subc
- Page 109 and 110: Chapter 5. Common Controls command
- Page 111 and 112: Chapter 5. Common Controls ((CSpinB
- Page 113 and 114: Chapter 5. Common Controls } The in
- Page 115 and 116: Chapter 5. Common Controls …… B
- Page 117 and 118: Chapter 5. Common Controls The “S
- Page 119 and 120: Chapter 5. Common Controls button
- Page 121 and 122: Chapter 5. Common Controls In this
- Page 123 and 124: Chapter 5. Common Controls (CBN_CLO
- Page 125 and 126: Chapter 5. Common Controls compare
- Page 127 and 128: Chapter 5. Common Controls } ptrEdi
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