
Add a second button to the About window in your application. Have the button display a different message from the one on the first window.
1: void CDay2Dlg::OnDfltmsg()
2: {
3: // TODO: Add your control notification handler code here
4:
5: ///////////////////////
6: // MY CODE STARTS HERE
7: ///////////////////////
8:
9: // Set the message to a default message
10: m_strMessage = "Enter a message here";
11:
12: // Update the screen
13: UpdateData(FALSE);
14:
15: ///////////////////////
16: // MY CODE ENDS HERE
17: ///////////////////////
18: }
1: void CDay2Dlg::OnCkenblpgm()
2: {
3: // TODO: Add your control notification handler code here
4:
5: ///////////////////////
6: // MY CODE STARTS HERE
7: ///////////////////////
8:
9: // Get the current values from the screen
10: UpdateData(TRUE);
11:
12: // Is the Enable Program Action check box checked?
13: if (m_bEnablePgm == TRUE)
14: {
15: // Yes, so enable all controls that have anything
16: // to do with running a program
17: GetDlgItem(IDC_PROGTORUN)->EnableWindow(TRUE);
18: GetDlgItem(IDC_RUNPGM)->EnableWindow(TRUE);
19: GetDlgItem(IDC_STATICPGM)->EnableWindow(TRUE);
20: }
21: else
22: {
23: // No, so disable all controls that have anything
24: // to do with running a program
25: GetDlgItem(IDC_PROGTORUN)->EnableWindow(FALSE);
26: GetDlgItem(IDC_RUNPGM)->EnableWindow(FALSE);
27: GetDlgItem(IDC_STATICPGM)->EnableWindow(FALSE);
28: }
29:
30: ///////////////////////
31: // MY CODE ENDS HERE
32: ///////////////////////
33: }
34:
35: void CDay2Dlg::OnCkshwpgm()
36: {
37: // TODO: Add your control notification handler code here
38:
39: ///////////////////////
40: // MY CODE STARTS HERE
41: ///////////////////////
42:
43: // Get the current values from the screen
44: UpdateData(TRUE);
45:
46: // Is the Show Program Action check box checked?
47: if (m_bShowPgm == TRUE)
48: {
49: // Yes, so show all controls that have anything
50: // to do with running a program
51: GetDlgItem(IDC_PROGTORUN)->ShowWindow(TRUE);
52: GetDlgItem(IDC_RUNPGM)->ShowWindow(TRUE);
53: GetDlgItem(IDC_STATICPGM)->ShowWindow(TRUE);
54: }
55: else
56: {
57: // No, so hide all controls that have anything
58: // to do with running a program
59: GetDlgItem(IDC_PROGTORUN)->ShowWindow(FALSE);
60: GetDlgItem(IDC_RUNPGM)->ShowWindow(FALSE);
61: GetDlgItem(IDC_STATICPGM)->ShowWindow(FALSE);
62: }
63:
64: ///////////////////////
65: // MY CODE ENDS HERE
66: ///////////////////////
67: }
1: void CDay2Dlg::OnRunpgm()
2: {
3: // TODO: Add your control notification handler code here
4:
5: ///////////////////////
6: // MY CODE STARTS HERE
7: ///////////////////////
8:
9: // Get the current values from the screen
10: UpdateData(TRUE);
11:
12: // Declare a local variable for holding the program name
13: CString strPgmName;
14:
15: // Copy the program name to the local variable
16: strPgmName = m_strProgToRun;
17:
18: // Make the program name all uppercase
19: strPgmName.MakeUpper();
20:
21: // Did the user select to run the Paint program?
22: if (strPgmName == "PAINT")
23: // Yes, run the Paint program
24: WinExec("pbrush.exe", SW_SHOW);
25:
26: // Did the user select to run the Notepad program?
27: if (strPgmName == "NOTEPAD")
28: // Yes, run the Notepad program
29: WinExec("notepad.exe", SW_SHOW);
30:
31: // Did the user select to run the Solitaire program?
32: if (strPgmName == "SOLITAIRE")
33: // Yes, run the Solitaire program
34: WinExec("sol.exe", SW_SHOW);
35:
36: // Run any other program name typed into the combo box
37: if ((strPgmName != "PAINT") && (strPgmName != "NOTEPAD") &&
38: (strPgmName != "SOLITAIRE"))
39: // Yes, run the program typed into the combo box
40: WinExec(strPgmName, SW_SHOW);
41:
42: ///////////////////////
43: // MY CODE ENDS HERE
44: ///////////////////////
45: }
((nFlags & MK_LBUTTON) == MK_LBUTTON)
1: void CMouseDlg::OnRButtonDown(UINT nFlags, CPoint point)
2: {
3: // TODO: Add your message handler code here and/or call default
4:
5: ///////////////////////
6: // MY CODE STARTS HERE
7: ///////////////////////
8:
9: // Set the current point as the starting point
10: m_iPrevX = point.x;
11: m_iPrevY = point.y;
12:
13: ///////////////////////
14: // MY CODE ENDS HERE
15: ///////////////////////
16:
17: CDialog::OnRButtonDown(nFlags, point);
18: }
1: void CMouseDlg::OnMouseMove(UINT nFlags, CPoint point)
2: {
3: // TODO: Add your message handler code here and/or call default
4:
5: ///////////////////////
6: // MY CODE STARTS HERE
7: ///////////////////////
8:
9: // Check to see if the left mouse button is down
10: if ((nFlags & MK_LBUTTON) == MK_LBUTTON)
11: {
12: // Get the Device Context
13: CClientDC dc(this);
14:
15: // Create a new pen
16: CPen lpen(PS_SOLID, 16, RGB(255, 0, 0));
17:
18: // Use the new pen
19: dc.SelectObject(&lpen);
20:
21: // Draw a line from the previous point to the current point
22: dc.MoveTo(m_iPrevX, m_iPrevY);
23: dc.LineTo(point.x, point.y);
24:
25: // Save the current point as the previous point
26: m_iPrevX = point.x;
27: m_iPrevY = point.y;
28: }
29:
30: // Check to see if the right mouse button is down
31: if ((nFlags & MK_RBUTTON) == MK_RBUTTON)
32: {
33: // Get the Device Context
34: CClientDC rdc(this);
35:
36: // Create a new pen
37: CPen rpen(PS_SOLID, 16, RGB(0, 0, 255));
38:
39: // Use the new pen
40: rdc.SelectObject(&rpen);
41:
42: // Draw a line from the previous point to the current point
43: rdc.MoveTo(m_iPrevX, m_iPrevY);
44: rdc.LineTo(point.x, point.y);
45:
46: // Save the current point as the previous point
47: m_iPrevX = point.x;
48: m_iPrevY = point.y;
49: }
50:
51: ///////////////////////
52: // MY CODE ENDS HERE
53: ///////////////////////
54:
55: CDialog::OnMouseMove(nFlags, point);
56: }
void CMouseDlg::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
// TODO: Add your message handler code here and/or call default
///////////////////////
// MY CODE STARTS HERE
///////////////////////
char lsChar; // The current character being pressed
HCURSOR lhCursor; // The handle to the cursor to be displayed
// Convert the key pressed to a character
lsChar = char(nChar);
// Is the character "A"
if (lsChar == `A')
{
// Load the arrow cursor
lhCursor = AfxGetApp()->LoadStandardCursor(IDC_ARROW);
// Set the cursor flag
m_bCursor = TRUE;
// Set the screen cursor
SetCursor(lhCursor);
}
// Is the character "B"
if (lsChar == `B')
{
// Load the I beam cursor
lhCursor = AfxGetApp()->LoadStandardCursor(IDC_IBEAM);
// Set the cursor flag
m_bCursor = TRUE;
// Set the screen cursor
SetCursor(lhCursor);
}
// Is the character "C"
if (lsChar == `C')
{
// Load the hourglass cursor
lhCursor = AfxGetApp()->LoadStandardCursor(IDC_WAIT);
// Set the cursor flag
m_bCursor = TRUE;
// Set the screen cursor
SetCursor(lhCursor);
}
// Is the character "D"
if (lsChar == `D')
{
// Load the cross hair cursor
lhCursor = AfxGetApp()->LoadStandardCursor(IDC_CROSS);
// Set the cursor flag
m_bCursor = TRUE;
// Set the screen cursor
SetCursor(lhCursor);
}
// Is the character "E"
if (lsChar == `E')
{
// Load the up arrow cursor
lhCursor = AfxGetApp()->LoadStandardCursor(IDC_UPARROW);
// Set the cursor flag
m_bCursor = TRUE;
// Set the screen cursor
SetCursor(lhCursor);
}
// Is the character "F"
if (lsChar == `F')
{
// Load the size cursor
lhCursor = AfxGetApp()->LoadStandardCursor(IDC_SIZEALL);
// Set the cursor flag
m_bCursor = TRUE;
// Set the screen cursor
SetCursor(lhCursor);
}
// Is the character "G"
if (lsChar == `G')
{
// Load the up/right-down/left size cursor
lhCursor = AfxGetApp()->LoadStandardCursor(IDC_SIZENWSE);
// Set the cursor flag
m_bCursor = TRUE;
// Set the screen cursor
SetCursor(lhCursor);
}
// Is the character "H"
if (lsChar == `H')
{
// Load the up/left-down/right size cursor
lhCursor = AfxGetApp()->LoadStandardCursor(IDC_SIZENESW);
// Set the cursor flag
m_bCursor = TRUE;
// Set the screen cursor
SetCursor(lhCursor);
}
// Is the character "I"
if (lsChar == `I')
{
// Load the left-right size cursor
lhCursor = AfxGetApp()->LoadStandardCursor(IDC_SIZEWE);
// Set the cursor flag
m_bCursor = TRUE;
// Set the screen cursor
SetCursor(lhCursor);
}
// Is the character "J"
if (lsChar == `J')
{
// Load the up-down size cursor
lhCursor = AfxGetApp()->LoadStandardCursor(IDC_SIZENS);
// Set the cursor flag
m_bCursor = TRUE;
// Set the screen cursor
SetCursor(lhCursor);
}
if (lsChar == `K')
{
// Load the no cursor
lhCursor = AfxGetApp()->LoadStandardCursor(IDC_NO);
// Set the cursor flag
m_bCursor = TRUE;
// Set the screen cursor
SetCursor(lhCursor);
}
if (lsChar == `L')
{
// Load the app starting cursor
lhCursor = AfxGetApp()->LoadStandardCursor(IDC_APPSTARTING);
// Set the cursor flag
m_bCursor = TRUE;
// Set the screen cursor
SetCursor(lhCursor);
}
if (lsChar == `M')
{
// Load the help cursor
lhCursor = AfxGetApp()->LoadStandardCursor(IDC_HELP);
// Set the cursor flag
m_bCursor = TRUE;
// Set the screen cursor
SetCursor(lhCursor);
}
// Is the character "X"
if (lsChar == `X')
{
// Load the arrow cursor
lhCursor = AfxGetApp()->LoadStandardCursor(IDC_ARROW);
// Set the cursor flag
m_bCursor = TRUE;
// Set the screen cursor
SetCursor(lhCursor);
// Exit the application
OnOK();
}
///////////////////////
// MY CODE ENDS HERE
///////////////////////
CDialog::OnKeyDown(nChar, nRepCnt, nFlags);
}
/////////////////////////////////////////////////////////////////////// CTimersDlg dialog
#define ID_CLOCK_TIMER 1
#define ID_COUNT_TIMER 2
class CTimersDlg : public CDialog
{
.
.
.
Update your application so that when the counter timer is started, the clock timer is reset to run at the same interval as the counter timer. When the counter timer is stopped, return the clock timer to a one-second interval.
To change the interval at which a timer is running, you need to first stop the timer and then restart it, as in Listing B.6.
1: void CTimersDlg::OnStarttime()
2: {
3: // TODO: Add your control notification handler code here
4:
5: ///////////////////////
6: // MY CODE STARTS HERE
7: ///////////////////////
8:
9: // Update the variables
10: UpdateData(TRUE);
11:
12: // Initialize the count
13: m_iCount = 0;
14: // Format the count for displaying
15: m_sCount.Format("%d", m_iCount);
16:
17: // Update the dialog
18: UpdateData(FALSE);
19: // Start the timer
20: SetTimer(ID_COUNT_TIMER, m_iInterval, NULL);
21:
22: // Stop the clock timer
23: KillTimer(ID_CLOCK_TIMER);
24: // Restart the clock timer with the counter interval
25: SetTimer(ID_CLOCK_TIMER, m_iInterval, NULL);
26:
27: // Enable the Stop Timer button
28: m_cStopTime.EnableWindow(TRUE);
29: // Disable the Start Timer button
30: m_cStartTime.EnableWindow(FALSE);
31:
32: ///////////////////////
33: // MY CODE ENDS HERE
34: ///////////////////////
35: }
36:
37: void CTimersDlg::OnStoptimer()
38: {
39: // TODO: Add your control notification handler code here
40:
41: ///////////////////////
42: // MY CODE STARTS HERE
43: ///////////////////////
44:
45: // Stop the timer
46: KillTimer(ID_COUNT_TIMER);
47:
48: // Stop the clock timer
49: KillTimer(ID_CLOCK_TIMER);
50: // Restart the clock timer with 1 second interval
51: SetTimer(ID_CLOCK_TIMER, 1000, NULL);
52:
53: // Disable the Stop Timer button
54: m_cStopTime.EnableWindow(FALSE);
55: // Enable the Start Timer button
56: m_cStartTime.EnableWindow(TRUE);
57:
58: ///////////////////////
59: // MY CODE ENDS HERE
60: ///////////////////////
61: }
CFileDialog m_ldFile(FALSE);
void CDialogsDlg::OnFileopen()
{
// TODO: Add your control notification handler code here
///////////////////////
// MY CODE STARTS HERE
///////////////////////
CFileDialog m_ldFile(TRUE);
// Show the File open dialog and capture the result
if (m_ldFile.DoModal() == IDOK)
{
// Get the filename selected
m_sResults = m_ldFile.GetPathName();
// Update the dialog
UpdateData(FALSE);
}
///////////////////////
// MY CODE ENDS HERE
///////////////////////
}
void CMsgDlg::OnYesno()
{
// TODO: Add your control notification handler code here
///////////////////////
// MY CODE STARTS HERE
///////////////////////
// Ask the user
m_iYesNo = MessageBox("Choose Yes or No", "Yes or No", ÂMB_YESNO);
///////////////////////
// MY CODE ENDS HERE
///////////////////////
}
void CDialogsDlg::OnYesno()
{
// TODO: Add your control notification handler code here
///////////////////////
// MY CODE STARTS HERE
///////////////////////
// What did the user answer
switch (m_dMsgDlg.m_iYesNo)
{
case IDYES: // Did the user answer YES?
m_sResults = "Yes!";
break;
case IDNO: // Did the user answer NO?
m_sResults = "No!";
break;
}
// Update the dialog
UpdateData(FALSE);
///////////////////////
// MY CODE ENDS HERE
///////////////////////
}
void CMenusDlg::OnContextMenu(CWnd* pWnd, CPoint point)
{
// TODO: Add your message handler code here and/or call Âdefault
///////////////////////
// MY CODE STARTS HERE
///////////////////////
// Declare local variables
CMenu *m_lMenu; // A pointer to the menu
CPoint m_pPoint; // A copy of the mouse position
// Copy the mouse position to a local variable
m_pPoint = point;
// Convert the position to a screen position
ClientToScreen(&m_pPoint);
// Get a pointer to the window menu
m_lMenu - GetMenu();
// Get a pointer to the first submenu
m_lMenu = m_lMenu->GetSubMenu(1);
// Show the Pop-up Menu
m_lMenu->TrackPopupMenu(TPM_CENTERALIGN + TPM_LEFTBUTTON,
m_pPoint.x, m_pPoint.y, this, NULL);
///////////////////////
// MY CODE ENDS HERE
///////////////////////
CDialog::OnRButtonDown(nFlags, point);
}
void CDay7Dlg::OnCbusetext()
{
// TODO: Add your control notification handler code here
///////////////////////
// MY CODE STARTS HERE
///////////////////////
// Update the variables with the dialog controls
UpdateData(TRUE);
// Using the font name for the font sample?
if (!m_bUseText)
// Using the font name
m_strDisplayText = m_strFontName;
else
// Using the entered text
m_strDisplayText = m_strSampText;
// Update the dialog
UpdateData(FALSE);
///////////////////////
// MY CODE ENDS HERE
///////////////////////
}
BOOL CDay7Dlg::OnInitDialog()
{
CDialog::OnInitDialog();
.
.
.
// TODO: Add extra initialization here
///////////////////////
// MY CODE STARTS HERE
///////////////////////
// Fill the font list box
FillFontList();
// Initialize the text to be entered
m_strSampText = "Testing";
// Copy the text to the font sample area
m_strDisplayText = m_strSampText;
// Initialize the check box
m_bUseText = TRUE;
// Update the dialog
UpdateData(FALSE);
///////////////////////
// MY CODE ENDS HERE
///////////////////////
return TRUE; // return TRUE unless you set the focus
// to a control
}
void CDay7Dlg::OnSelchangeLfonts()
{
// TODO: Add your control notification handler code here
///////////////////////
// MY CODE STARTS HERE
///////////////////////
// Update the variables with the dialog controls
UpdateData(TRUE);
// Using the font name for the font sample?
if (!m_bUseText)
{
// Copy the font name to the font sample
m_strDisplayText = m_strFontName;
// Update the dialog with the variables
UpdateData(FALSE);
}
// Set the font for the sample
SetMyFont();
///////////////////////
// MY CODE ENDS HERE
///////////////////////
}
void CDay7Dlg::OnChangeEsamptext()
{
// TODO: If this is a RICHEDIT control, the control will not
// send this notification unless you override the
// CDialog::OnInitialUpdate()
// function and call CRichEditCrtl().SetEventMask()
// with the EN_CHANGE flag ORed into the mask.
// TODO: Add your control notification handler code here
///////////////////////
// MY CODE STARTS HERE
///////////////////////
// Update the variables with the dialog controls
UpdateData(TRUE);
// Using the text for the font sample?
if (m_bUseText)
{
// Copy the current text to the font sample
m_strDisplayText = m_strSampText;
// Update the dialog with the variables
UpdateData(FALSE);
}
///////////////////////
// MY CODE ENDS HERE
///////////////////////
}
void CDay7Dlg::OnCbitalic()
{
// TODO: Add your control notification handler code here
///////////////////////
// MY CODE STARTS HERE
///////////////////////
// Update the variables with the dialog controls
UpdateData(TRUE);
// Set the font for the sample
SetMyFont();
///////////////////////
// MY CODE ENDS HERE
///////////////////////
}
void CDay7Dlg::SetMyFont()
{
CRect rRect; // The rectangle of the display area
int iHeight; // The height of the display area
int iItalic = 0; // Italicize the font?
// Has a font been selected?
if (m_strFontName != "")
{
// Get the dimensions of the font sample display area
m_ctlDisplayText.GetWindowRect(&rRect);
// Calculate the area height
iHeight = rRect.top - rRect.bottom;
// Make sure the height is positive
if (iHeight < 0)
iHeight = 0 - iHeight;
// Should the font be italicized?
If (m_bItalic)
iItalic = 1;
// Create the font to be used
m_fSampFont.CreateFont((iHeight - 5), 0, 0, 0,
FW_NORMAL, iItalic, 0, 0, DEFAULT_CHARSET,
OUT_CHARACTER_PRECIS, CLIP_CHARACTER_PRECIS,
DEFAULT_QUALITY, DEFAULT_PITCH |
FF_DONTCARE, m_strFontName);
// Set the font for the sample display area
m_ctlDisplayText.SetFont(&m_fSampFont);
}
}
1: void CPaintDlg::OnSize(UINT nType, int cx, int cy)
2: {
3: CDialog::OnSize(nType, cx, cy);
4:
5: // TODO: Add your message handler code here
6: // Redraw the window
7: Invalidate();
8:}
1: void CPaintDlg::DrawRegion(CPaintDC *pdc, int iColor, int iTool, int ÂiShape)
2: {
3: // Declare and create the pens
.
.
.
19: CBrush lVertBrush(HS_VERTICAL, m_crColors[iColor]);
20: CBrush lNullBrush(RGB(192, 192, 192));
21:
22: CBitmap lBitmap;
23: lBitmap.LoadBitmap(IDB_BITMAPBRUSH);
24: CBrush lBitmapBrush(&lBitmap);
25:
26: // Calculate the size of the drawing regions
27: CRect lRect;
28: GetClientRect(lRect);
.
.
.
37: int i;
38: // Loop through all of the brushes and pens
39: for (i = 0; i < 8; i++)
40: {
41: switch (i)
42: {
.
.
.
103: pdc->SelectObject(&lVertBrush);
104: break;
105: case 7: // Null - Bitmap
106: // Determine the location for this figure.
107: lDrawRect.left = lDrawRect.left + liHorz;
108: lDrawRect.right = lDrawRect.left + liWidth;
109: // Select the appropriate pen and brush
110: pdc->SelectObject(&lNullPen);
111: pdc->SelectObject(&lBitmapBrush);
112: break;
113: }
114: // Which tool are we using?
.
.
.
126: pdc->SelectObject(lOldBrush);
127: pdc->SelectObject(lOldPen);
128:}
Modify the application so that the user can double-click a column header and make it the first column in the grid.
Using the Class Wizard, add a function to the DblClick event message for the grid control.
Edit the function in exercise 1 to add the following code:
void CActiveXDlg::OnDblClickMsfgrid()
{
// TODO: Add your control notification handler code here
///////////////////////
// MY CODE STARTS HERE
///////////////////////
// Did the user click on a data row and not the
// header row?
if (m_ctlFGrid.GetMouseRow() != 0)
{
// If so, then zero out the column variable
// and exit
m_iMouseCol = 0;
return;
}
// Save the column clicked on
m_iMouseCol = m_ctlFGrid.GetMouseCol();
// If the selected column was the first column,
// there's nothing to do
if (m_iMouseCol == 0)
return;
// Turn the control redraw off
m_ctlFGrid.SetRedraw(FALSE);
// Change the selected column position
m_ctlFGrid.SetColPosition(m_iMouseCol, 0);
// Resort the grid
DoSort();
// Turn redraw back on
m_ctlFGrid.SetRedraw(TRUE);
///////////////////////
// MY CODE ENDS HERE
///////////////////////
}
Add another pull-down menu to control the width of the pen used for drawing. Give it the following settings:
| Menu Entry | Width Setting |
| Very Thin | 1 |
| Thin | 8 |
| Medium | 16 |
| Thick | 24 |
| Very Thick | 32 |
Follow these steps:
1: CLine::CLine(CPoint ptFrom, CPoint ptTo, COLORREF crColor, UINT nWidth)
2: {
3: //Initialize the from and to points
4: m_ptFrom = ptFrom;
5: m_ptTo = ptTo;
6: m_crColor = crColor;
7: m_nWidth = nWidth;
8: }
1: void CLine::Draw(CDC * pDC)
2: {
3: // Create a pen
4: CPen lpen (PS_SOLID, m_nWidth, m_crColor);
5:
6: // Set the new pen as the drawing object
7: CPen* pOldPen = pDC->SelectObject(&lpen);
8: // Draw the line
9: pDC->MoveTo(m_ptFrom);
10: pDC->LineTo(m_ptTo);
11: // Reset the previous pen
12: pDC->SelectObject(pOldPen);
13: }
1: void CLine::Serialize(CArchive &ar)
2: {
3: CObject::Serialize(ar);
4:
5: if (ar.IsStoring())
6: ar << m_ptFrom << m_ptTo << (DWORD) m_crColor << m_nWidth;
7: else
8: ar >> m_ptFrom >> m_ptTo >> (DWORD) m_crColor >> m_nWidth;
9: }
1: BOOL CDay10Doc::OnNewDocument()
2: {
3: if (!CDocument::OnNewDocument())
4: return FALSE;
5:
6: // TODO: add reinitialization code here
7: // (SDI documents will reuse this document)
8:
9: ///////////////////////
10: // MY CODE STARTS HERE
11: ///////////////////////
12:
13: // Initialize the color to black
14: m_nColor = ID_COLOR_BLACK - ID_COLOR_BLACK;
15: // Initialize the width to thin
16: m_nWidth = ID_WIDTH_VTHIN - ID_WIDTH_VTHIN;
17:
18: ///////////////////////
19: // MY CODE ENDS HERE
20: ///////////////////////
21:
22: return TRUE;
23: }
1: CLine * CDay10Doc::AddLine(CPoint ptFrom, CPoint ptTo)
2: {
3: static UINT nWidths[5] = { 1, 8, 16, 24, 32};
4:
5: // Create a new CLine object
6: CLine *pLine = new CLine(ptFrom, ptTo,
Âm_crColors[m_nColor], nWidths[m_nWidth]);
7: try
8: {
9: // Add the new line to the object array
10: m_oaLines.Add(pLine);
11: // Mark the document as dirty
12: SetModifiedFlag();
13: }
14: // Did we run into a memory exception?
15: catch (CMemoryException* perr)
16: {
17: // Display a message for the user, giving him or her the
18: // bad news
19: AfxMessageBox("Out of memory", MB_ICONSTOP | MB_OK);
20: // Did we create a line object?
21: if (pLine)
22: {
23: // Delete it
24: delete pLine;
25: pLine = NULL;
26: }
27: // Delete the exception object
28: perr->Delete();
29: }
30: return pLine;
31: }
1: UINT CDay10Doc::GetWidth()
2: {
3: // Return the current width
4: return ID_WIDTH_VTHIN + m_nWidth;
5: }
| Object | Property | Setting |
| Menu Entry | ID | ID_WIDTH_VTHIN |
| Caption | &Very Thin | |
| Menu Entry | ID | ID_WIDTH_THIN |
| Caption | Thi&n | |
| Menu Entry | ID | ID_WIDTH_MEDIUM |
| Caption | &Medium | |
| Menu Entry | ID | ID_WIDTH_THICK |
| Caption | Thic&k | |
| Menu Entry | ID | ID_WIDTH_VTHICK |
| Caption | Very &Thick |
1: void CDay10Doc::OnWidthVthin()
2: {
3: // TODO: Add your command handler code here
4:
5: ///////////////////////
6: // MY CODE STARTS HERE
7: ///////////////////////
8:
9: // Set the current width to Very Thin
10: m_nColor = ID_WIDTH_VTHIN - ID_WIDTH_VTHIN;
11:
12: ///////////////////////
13: // MY CODE ENDS HERE
14: ///////////////////////
15: }
16:
17: void CDay10Doc::OnUpdateWidthVthin(CCmdUI* pCmdUI)
18: {
19: // TODO: Add your command update UI handler code here
20:
21: ///////////////////////
22: // MY CODE STARTS HERE
23: ///////////////////////
24:
25: // Determine if the Very Thin menu entry should be checked
26: pCmdUI->SetCheck(GetWidth() == ID_WIDTH_VTHIN ? 1 : 0);
27:
28: ///////////////////////
29: // MY CODE ENDS HERE
30: ///////////////////////
31: }
1: void CDay10Doc::OnWidthThin()
2: {
3: // TODO: Add your command handler code here
4:
5: ///////////////////////
6: // MY CODE STARTS HERE
7: ///////////////////////
8:
9: // Set the current width to Thin
10: m_nColor = ID_WIDTH_THIN - ID_WIDTH_VTHIN;
11:
12: ///////////////////////
13: // MY CODE ENDS HERE
14: ///////////////////////
15: }
16:
17: void CDay10Doc::OnUpdateWidthThin(CCmdUI* pCmdUI)
18: {
19: // TODO: Add your command update UI handler code here
20:
21: ///////////////////////
22: // MY CODE STARTS HERE
23: ///////////////////////
24:
25: // Determine if the Thin menu entry should be checked
26: pCmdUI->SetCheck(GetWidth() == ID_WIDTH_THIN ? 1 : 0);
27:
28: ///////////////////////
29: // MY CODE ENDS HERE
30: ///////////////////////
31: }
Add the pull-down and context menus for the width, using the same pen widths as yesterday.
Follow these steps:
.
.
.
1: #ifdef _DEBUG
2: virtual void AssertValid() const;
3: virtual void Dump(CDumpContext& dc) const;
4: #endif
5:
6: protected:
7:
8: // Generated message map functions
9: protected:
10: afx_msg void OnColorCommand(UINT nID);
11: afx_msg void OnWidthCommand(UINT nID);
12: afx_msg void OnUpdateColorUI(CCmdUI* pCmdUI);
13: afx_msg void OnUpdateWidthUI(CCmdUI* pCmdUI);
14: //{{AFX_MSG(CDay11Doc)
15: // NOTE - the ClassWizard will add and remove member functions //here.
16: // DO NOT EDIT what you see in these blocks of generated //code !
17: //}}AFX_MSG
18: DECLARE_MESSAGE_MAP()
19: private:
20: UINT m_nColor;
21: CObArray m_oaLines;
22: };
1://///////////////////////////////////////////////////////////////////// 2: // CDay11Doc
3:
4: IMPLEMENT_DYNCREATE(CDay11Doc, CDocument)
5:
6: BEGIN_MESSAGE_MAP(CDay11Doc, CDocument)
7: ON_COMMAND_RANGE(ID_COLOR_BLACK, ID_COLOR_WHITE, OnColorCommand)
8: ON_COMMAND_RANGE(ID_WIDTH_VTHIN, ID_WIDTH_VTHICK, OnWidthCommand)
9: ON_UPDATE_COMMAND_UI_RANGE(ID_COLOR_BLACK, ID_COLOR_WHITE, ÂOnUpdateColorUI)
10: ON_UPDATE_COMMAND_UI_RANGE(ID_WIDTH_VTHIN, ID_WIDTH_VTHICK, ÂOnUpdateWidthUI)
11: //{{AFX_MSG_MAP(CDay11Doc)
12: // NOTE - the ClassWizard will add and remove mapping macros //here.
13: // DO NOT EDIT what you see in these blocks of generated //code!
14: //}}AFX_MSG_MAP
15: END_MESSAGE_MAP()
16:
17: const COLORREF CDay11Doc::m_crColors[8] = {
18: RGB( 0, 0, 0), // Black
19: RGB( 0, 0, 255), // Blue
.
.
.
1: void CDay11Doc::OnWidthCommand(UINT nID)
2: {
3: // Set the current width
4: m_nWidth = nID - ID_WIDTH_VTHIN;
5: }
6:
7: void CDay11Doc::OnUpdateWidthUI(CCmdUI* pCmdUI)
8: {
9: // Determine if the menu entry should be checked
10: pCmdUI->SetCheck(GetWidth() == pCmdUI->m_nID ? 1 : 0);
11: }
static UINT indicators[] =
{
ID_SEPARATOR, // status line indicator
ID_INDICATOR_WIDTH,
ID_INDICATOR_COLOR,
ID_INDICATOR_CAPS,
ID_INDICATOR_NUM,
ID_INDICATOR_SCRL,
};
void CToolbarDoc::OnUpdateIndicatorWidth(CCmdUI *pCmdUI)
{
CString strWidth;
// What is the current width?
switch (m_nWidth)
{
case 0: // Very Thin
strWidth = "VERY THIN";
break;
case 1: // Thin
strWidth = "THIN";
break;
case 2: // Medium
strWidth = "MEDIUM";
break;
case 3: // Thick
strWidth = "THICK";
break;
case 4: // Very Thick
strWidth = "VERY THICK";
break;
}
// Enable the status bar pane
pCmdUI->Enable(TRUE);
// Set the text of the status bar pane
// to the current width
pCmdUI->SetText(strWidth);
}
////////////////////////////////////////////////////////////////
// CToolbarDoc
IMPLEMENT_DYNCREATE(CToolbarDoc, CDocument)
BEGIN_MESSAGE_MAP(CToolbarDoc, CDocument)
ON_UPDATE_COMMAND_UI(ID_INDICATOR_WIDTH,
ÂOnUpdateIndicatorWidth)
ON_UPDATE_COMMAND_UI(ID_INDICATOR_COLOR,
ÂOnUpdateIndicatorColor)
//{{AFX_MSG_MAP(CToolbarDoc)
ON_UPDATE_COMMAND_UI(ID_WIDTH_VTHIN, OnUpdateWidthVthin)
.
.
ON_COMMAND(ID_WIDTH_VTHIN, OnWidthVthin)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
Add a couple of radio buttons to the form to specify the person's sex, as in Figure 13.5. Incorporate this change into the CPerson class to make the field persistent.
In the window designer, add the two radio buttons and the static text prompt. Specify the control properties in Table B.2.
| Object | Property | Setting |
| Static Text | ID | IDC_STATIC |
| Caption | Sex: | |
| Radio Button | ID | IDC_RMALE |
| Caption | Mal&e | |
| Group | Checked | |
| Radio Button | ID | IDC_RFEMALE |
| Caption | &Female |
Move the mnemonic in the First button from &First to Fi&rst to prevent a conflict with the new radio buttons.
Attach a variable to the new radio buttons as in Table B.3.
| Object | Name | Category | Type |
| IDC_RMALE | m_iSex | Value | int |
Increment the version number in the IMPLEMENT_SERIAL macro in the CPerson class. Add a new member variable to the CPerson class. Specify the type as int, the name as m_iSex, and the access as private. Update the CPerson constructor function, adding the m_iSex variable to the initializations as in line 8 of Listing B.20.
1: CPerson::CPerson()
2: {
3: // Initialize the class variables
4: m_iMaritalStatus = 0;
5: m_iAge = 0;
6: m_bEmployed = FALSE;
7: m_sName = "";
8: m_iSex = 0;
9: }
Add the inline functions to the CPerson class declaration to set and get the value of this new variable, as in lines 9 and 15 of Listing B.21.
1: class CPerson : public CObject
2: {
3: DECLARE_SERIAL (CPerson)
4: public:
5: // Functions for setting the variables
6: void SetEmployed(BOOL bEmployed) { m_bEmployed = bEmployed;}
7: void SetMaritalStat(int iStat) { m_iMaritalStatus = iStat;}
8: void SetAge(int iAge) { m_iAge = iAge;}
9: void SetSex(int iSex) { m_iSex = iSex;}
10: void SetName(CString sName) { m_sName = sName;}
11: // Functions for getting the current settings of the variables
12: BOOL GetEmployed() { return m_bEmployed;}
13: int GetMaritalStatus() { return m_iMaritalStatus;}
14: int GetAge() {return m_iAge;}
15: int GetSex() {return m_iSex;}
16: CString GetName() {return m_sName;}
17: CPerson();
18: virtual ~CPerson();
19:
20: private:
21: BOOL m_bEmployed;
22: int m_iMaritalStatus;
23: int m_iAge;
24: CString m_sName;
25: };
Update the Serialize function in the CPerson class to include the m_iSex variable as in lines 9 and 12 of Listing B.22.
1: void CPerson::Serialize(CArchive &ar)
2: {
3: // Call the ancestor function
4: CObject::Serialize(ar);
5:
6: // Are we writing?
7: if (ar.IsStoring())
8: // Write all of the variables, in order
9: ar << m_sName << m_iAge << m_iMaritalStatus << m_bEmployed <<
Âm_iSex;
10: else
11: // Read all of the variables, in order
12: ar >> m_sName >> m_iAge >> m_iMaritalStatus >> m_bEmployed >>
Âm_iSex;
13:
14: }
Modify the PopulateView function in the view object to include the Sex variable in the data exchange, as in line 19 of Listing B.23.
1: void CSerializeView::PopulateView()
2: {
3: // Get a pointer to the current document
4: CSerializeDoc* pDoc = GetDocument();
5: if (pDoc)
6: {
7: // Display the current record position in the set
8: m_sPosition.Format("Record %d of %d", pDoc->GetCurRecordNbr(),
9: pDoc->GetTotalRecords());
10: }
11: // Do we have a valid record object?
12: if (m_pCurPerson)
13: {
14: // Yes, get all of the record values
15: m_bEmployed = m_pCurPerson->GetEmployed();
16: m_iAge = m_pCurPerson->GetAge();
17: m_sName = m_pCurPerson->GetName();
18: m_iMaritalStatus = m_pCurPerson->GetMaritalStatus();
19: m_iSex = m_pCurPerson->GetSex();
20: }
21: // Update the display
22: UpdateData(FALSE);
23: }
Add an event handler for the clicked event of both new radio buttons, using the same function for both event handlers. Update the record object's field using the Set function, as in Listing B.24.
1: void CSerializeView::OnSex()
2: {
3: // TODO: Add your control notification handler code here
4:
5: // Sync the data in the form with the variables
6: UpdateData(TRUE);
7: // If we have a valid person object, pass the data changes to it
8: if (m_pCurPerson)
9: m_pCurPerson->SetSex(m_iSex);
10: // Get a pointer to the document
11: CSerializeDoc * pDoc = GetDocument();
12: if (pDoc)
13: // Set the modified flag in the document
14: pDoc->SetModifiedFlag();
15: }
Add a menu entry and dialog to let the user indicate the record number to move to, and then move to that record.
FIGURE B.1.
The Move To dialog layout.
| Object | Property | Setting |
| Static Text | ID | IDC_STATIC |
| Caption | Move to record: | |
| Edit Box | ID | IDC_ERECNBR |
| Object | Property | Setting |
| Menu Entry | ID | IDM_RECORD_MOVE |
| Caption | &Move To... | |
| Prompt | Move to a specific record\nMove To |
1: void CTestdb5View::OnRecordMove()
2: {
3: // TODO: Add your command handler code here
4: // Create an instance of the Move To dialog
5: CMoveToDlg dlgMoveTo;
6: // Get the row number to move to
7: if (dlgMoveTo.DoModal() == IDOK)
8: {
9: // Get a pointer to the record set
10: CRecordset* pSet = OnGetRecordset();
11: // Make sure that there are no outstanding changes to be saved
12: if (pSet->CanUpdate() && !pSet->IsDeleted())
13: {
14: pSet->Edit();
15: if (!UpdateData())
16: return;
17:
18: pSet->Update();
19: }
20: // Set the new position
21: pSet->SetAbsolutePosition(dlgMoveTo.m_lRowNbr);
22: // Update the form
23: UpdateData(FALSE);
24: }
25: }
1: // DbOdbcView.cpp : implementation of the CDbOdbcView class 2: // 3: 4: #include "stdafx.h" 5: #include "DbOdbc.h" 6: 7: #include "DbOdbcSet.h" 8: #include "DbOdbcDoc.h" 9: #include "DbOdbcView.h"
10: #include "MoveToDlg.h"
::CoInitialize(NULL);
pCmd->ActiveConnection = pConn;
_RecordsetPtr pRs;
pRs = pCmd->Execute();
_RecordsetPtr pRs; pRs.CreateInstance(__uuidof(Recordset));
pRs->PutRefSource(pCmd);
Enable and disable the navigation menus and toolbar buttons based on whether the recordset is at the beginning of file (BOF) or end of file (EOF, renamed to EndOfFile).
Add event-handler functions to the document class for the navigation menu entries' UPDATE_COMMAND_UI event message. Edit these functions, adding the code in Listing B.27 to the functions for the First and Previous menus, and the code in Listing B.28 to the functions for the Last and Next menus.
1: void CDbAdoDoc::OnUpdateDataFirst(CCmdUI* pCmdUI)
2: {
3: // TODO: Add your command update UI handler code here
4: // Does the record set exist?
5: if (m_pRs)
6: {
7: // Are we at the BOF?
8: if (m_pRs->BOF)
9: pCmdUI->Enable(FALSE);
10: else
11: pCmdUI->Enable(TRUE);
12: }
13: }
1: void CDbAdoDoc::OnUpdateDataLast(CCmdUI* pCmdUI)
2: {
3: // TODO: Add your command update UI handler code here
4: // Does the record set exist?
5: if (m_pRs)
6: {
7: // Are we at the EOF?
8: if (m_pRs->EndOfFile)
9: pCmdUI->Enable(FALSE);
10: else
11: pCmdUI->Enable(TRUE);
12: }
13: }
Separate the CLine class into a different library module from the drawing class so that you have two library modules instead of one. Link them into the test application.
1: // ModArt.cpp: implementation of the CModArt class. 2: // 3: ////////////////////////////////////////////////////////////////////// 4: 5: #include <stdlib.h> 6: #include <time.h> 7: 8: #include "stdafx.h" 9: #include "..\Line\Line.h"
10: #include "ModArt.h"
1: // ModArt.cpp: implementation of the CModArt class. 2: // 3: ///////////////////////////////////////////////////////////////////// 4: 5: #include <stdlib.h> 6: #include <time.h> 7: 8: #include "stdafx.h" 9: #include "..\LineDll\Line.h"
10: #include "ModArt.h"
1: CLine::CLine(CPoint ptFrom, CPoint ptTo, UINT nWidth, COLORREF crColor)
2: {
3: m_ptFrom = ptFrom;
4: m_ptTo = ptTo;
5: m_nWidth = 1;
6: m_crColor = crColor;
7: }
1: BOOL CTaskingApp::OnIdle(LONG lCount)
2: {
3: // TODO: Add your specialized code here and/or call the base class
4:
5: // Call the ancestor's idle processing
6: BOOL bRtn = CWinApp::OnIdle(lCount);
7:
8: // Get the position of the first document template
9: POSITION pos = GetFirstDocTemplatePosition();
10: // Do we have a valid template position?
11: if (pos)
12: {
13: // Get a pointer to the document template
14: CDocTemplate* pDocTemp = GetNextDocTemplate(pos);
15: // Do we have a valid pointer?
16: if (pDocTemp)
17: {
18: // Get the position of the first document
19: POSITION dPos = pDocTemp->GetFirstDocPosition();
20: // Do we have a valid document position?
21: if (dPos)
22: {
23: // Get a pointer to the document
24: CTaskingDoc* pDocWnd =
25: (CTaskingDoc*)pDocTemp->GetNextDoc(dPos);
26: // Do we have a valid pointer?
27: if (pDocWnd)
28: {
29: // Get the position of the view
30: POSITION vPos = pDocWnd->GetFirstViewPosition();
31: // Do we have a valid view position?
32: if (vPos)
33: {
34: // Get a pointer to the view
35: CTaskingView* pView =
Â(CTaskingView*)pDocWnd->GetNextView(vPos);
36: // Do we have a valid pointer?
37: if (pView)
38: {
39: // Should we spin the first idle thread?
40: if (pView->m_bOnIdle1)
41: {
42: // Spin the first idle thread
43: pDocWnd->DoSpin(0);
44: bRtn = TRUE;
45: }
46: // Should we spin the second idle thread?
47: if (pView->m_bOnIdle2)
48: {
49: // Spin the second idle thread
50: pDocWnd->DoSpin(2);
51: bRtn = TRUE;
52: }
53: }
54: }
55: }
56: }
57: }
58: }
59: return bRtn;
60: }
1: void CTaskingDoc::SuspendSpinner(int nIndex, BOOL bSuspend)
2: {
3: // if suspending the thread
4: if (!bSuspend)
5: {
6: // Is the pointer for the thread valid?
7: if (m_pSpinThread[nIndex])
8: {
9: // Get the handle for the thread
10: HANDLE hThread = m_pSpinThread[nIndex]->m_hThread;
11: // Wait for the thread to die
12: ::WaitForSingleObject (hThread, INFINITE);
13: }
14: }
15: else // We are running the thread
16: {
17: int iSpnr;
18: int iPriority;
19: // Which spinner to use?
20: switch (nIndex)
21: {
22: case 0:
23: iSpnr = 1;
24: iPriority = THREAD_PRIORITY_NORMAL;
25: break;
26: case 1:
27: iSpnr = 3;
28: iPriority = THREAD_PRIORITY_LOWEST;
29: break;
30: }
31: // Start the thread, passing a pointer to the spinner
32: m_pSpinThread[nIndex] = AfxBeginThread(ThreadFunc,
33: (LPVOID)&m_cSpin[iSpnr], iPriority);
34: }
35: }
1: void CSquiggleCtrl:: GenNewDrawing()
2: {
3: // TODO: Add your specialized code here and/or call the base class
4: // Set the flag so a new drawing will be generated
5: m_bGenNewDrawing = TRUE;
6: // Invalidate the control to trigger the OnDraw function
7: Invalidate();
8: }
1: BOOL CSquiggleCtrl::SaveDrawing(LPCTSTR sFileName)
2: {
3: // TODO: Add your dispatch handler code here
4: try
5: {
6: // Create a CFile object
7: CFile lFile(sFileName, CFile::modeWrite);
8: // Create a CArchive object to store the file
9: CArchive lArchive(&lFile, CArchive::store);
10: // Store the file
11: m_maDrawing.Serialize(lArchive);
12: }
13: catch (CFileException err)
14: {
15: return FALSE;
16: }
17: return TRUE;
18: }
The server application that you wrote can handle only a single connection at a time. If a second application tries to open a connection to it while it has an existing connection to an application, the server application will crash. The server tries to accept the second connection into the socket that is already connected to the first client application. Add a third socket object to the application that will be used to reject additional client connections until the first client closes the connection.
Follow these steps:
1: void CSockDlg::OnAccept()
2: {
3: if (m_bConnected)
4: {
5: // Create a rejection socket
6: CAsyncSocket sRjctSock;
7: // Create a message to send
8: CString strMsg = "Too many connections, try again later.";
9: // Accept using the rejection socket
10: m_sListenSocket.Accept(sRjctSock);
11: // Send the rejection message
12: sRjctSock.Send(LPCTSTR(strMsg), strMsg.GetLength());
13: // Close the socket
14: sRjctSock.Close();
15: }
16: else
17: {
18: // Accept the connection request
19: m_sListenSocket.Accept(m_sConnectSocket);\
20: // Mark the socket as connected
21: m_bConnected = TRUE;
22: // Enable the text and message controls
23: GetDlgItem(IDC_EMSG)->EnableWindow(TRUE);
24: GetDlgItem(IDC_BSEND)->EnableWindow(TRUE);
25: GetDlgItem(IDC_STATICMSG)->EnableWindow(TRUE);
26: }
27: }
| Object | Property | Setting |
| Menu Entry | ID | IDM_GO_SEARCH |
| Caption | &Search | |
| Prompt | Search the Web\nSearch |
1: void CWebBrowseView::OnGoSearch()
2: {
3: // TODO: Add your command handler code here
4:
5: // Go to the search page
6: GoSearch();
7: }
| Object | Property | Setting |
| Menu Entry | ID | IDM_GO_START |
| Caption | S&tart Page | |
| Prompt | Go to the start page\nHome |
1: void CWebBrowseView::OnGoStart()
2: {
3: // TODO: Add your command handler code here
4:
5: // Go to the start page
6: GoHome();
7: }
1: void CWebBrowseView::OnUpdateViewStop(CCmdUI* pCmdUI)
2: {
3: // TODO: Add your command update UI handler code here
4:
5: // Enable the button if busy
6: pCmdUI->Enable(GetBusy());
7: }
© Copyright, Macmillan Computer Publishing. All rights reserved.