Click Here!
home account info subscribe login search My ITKnowledge FAQ/help site map contact us


 
Brief Full
 Advanced
      Search
 Search Tips
To access the contents, click the chapter and section titles.

Fast Track Visual C++ 6.0 Programming
(Publisher: John Wiley & Sons, Inc.)
Author(s): Steve Holzner
ISBN: 0471312908
Publication Date: 09/01/98

Bookmark It

Search this book:
 
Previous Table of Contents Next


Setting Up the New Windows Message

To set up the constant WM_MAX, we define it in the overall header file for the project, Threads.h. This new constant is used as a Windows message, but we don’t want to conflict with other Windows messages that the view object may handle in some other way. Visual C++ defines a constant, WM_USER, as the lowest Windows message available for us to use without conflicting with other Windows messages, so we set up WM_MAX as that value plus 1.

// Threads.h : main header file for the THREADS application
//

#if !defined(AFX_THREADS_H__A880E545_A6EB_11D1_887F_D42B07C10710__INCLUDED_)
#define AFX_THREADS_H__A880E545_A6EB_11D1_887F_D42B07C10710__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#ifndef __AFXWIN_H__
    #error include ‘stdafx.h’ before including this file for PCH
#endif

#include “resource.h”       // main symbols

#define WM_MAX (WM_USER + 1)                                    ⇐
    .
    .

    .

Now we connect a function, OnMaxFound(), to WM_MAX so the view can call that function when it gets the WM_MAX message. First, we declare that function. Like all Windows message-handling functions, it is passed two parameters, wParam (a word-length parameter) and lParam (a long parameter, usually a pointer), but because we made both of those 0, we ignore them.

class CThreadsView : public CView
 {
protected: // create from serialization only
    CThreadsView();
    DECLARE_DYNCREATE(CThreadsView)

// Attributes
public:
    CThreadsDoc* GetDocument();
    SData data;
    CWinThread* Thread;
    void OnMaxFound(WPARAM wParam, LPARAM lParam);                  ⇐
Next, we connect WM_MAX to OnMaxFound() with a macro in the message map
section of our view‘s class (which ClassWizard usually maintains):
/////////////////////////////////////////////////////////////////////////////
// CThreadsView

IMPLEMENT_DYNCREATE(CThreadsView, CView)

BEGIN_MESSAGE_MAP(CThreadsView, CView)
    //{{AFX_MSG_MAP(CThreadsView)
    ON_COMMAND(ID_FILE_FINDMAX, OnFileFindmax)
    ON_MESSAGE(WM_MAX, OnMaxFound)                                  ⇐
    //}}AFX_MSG_MAP
    // Standard printing commands
    ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint)
    ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint)
    ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview)

END_MESSAGE_MAP()

The only thing left to do is to write OnMaxFound() to interpret the results of the thread’s work.

Reporting the Thread’s Results

When OnMaxFound() is called, the new thread has already notified the view that it has completed its task and has sent the WM_MAX message. That means that the maximum value in the array is in the max element in the data structure, and all we need to do is to display that result in the view.

Add CThreadsView::OnMaxFound() to the view class now.

void CThreadsView::OnMaxFound(WPARAM wParam, LPARAM lParam)
 {

}

The maximum value in the array is in the data structure’s max element, which we reach as data.max. We place that value, along with the message “Max of the array = ”, into a character string named FormattedString.

void CThreadsView::OnMaxFound(WPARAM wParam, LPARAM lParam)
 {
    char FormattedString[100];                                      ⇐
    wsprintf(FormattedString, “Max of the array = %d”, data.max);      ⇐
      .
      .
      .

}

We also set up a CString object in the document named text and put the formatted text string into that object.

void CThreadsView::OnMaxFound(WPARAM wParam, LPARAM lParam)
 {
    CThreadsDoc* pDoc = GetDocument();                              ⇐
    ASSERT_VALID(pDoc);                                             ⇐

    char FormattedString[100];
    wsprintf(FormattedString, “Max of the array = %d”, data.max);
    pDoc->text = FormattedString;                                 ⇐
      .
      .
      .

}

Finally, we terminate the new thread with TerminateThread(), passing the pointer to the thread object, Thread, and an exit code of 0 as well as invalidating the view to display our result.

void CThreadsView::OnMaxFound(WPARAM wParam, LPARAM lParam)
 {
    CThreadsDoc* pDoc = GetDocument();
    ASSERT_VALID(pDoc);

    char FormattedString[100];
    wsprintf(FormattedString, “Max of the array = %d”, data.max);
    pDoc->text = FormattedString;

    TerminateThread(Thread, 0);                                     ⇐

    Invalidate();                                                   ⇐
}


Figure 9.1  Using the onMouseOut event.

In the view’s OnDraw(), we simply display the CString named text that holds our result in the view.

void CThreadsView::OnDraw(CDC* pDC)
 {
    CThreadsDoc* pDoc = GetDocument();
    ASSERT_VALID(pDoc);

    pDC->TextOut(0, 0, pDoc->text);                             ⇐

}

Run the program now and select the Find max item in the File menu. This launches the new thread, which finds the maximum value in the array and sends the Windows message to the view. The result appears in Figure 9.1.

Now we’ve created our first multitasking program with Visual C++.

The code for this example, ThreadsView.h and ThreadsView.cpp, appears in Listing 9.1.


Listing 9.1 ThreadsView.h and ThreadsView.cpp

// ThreadsView.h : interface of the CThreadsView class
//
/////////////////////////////////////////////////////////////////////////////

#if !defined(AFX_THREADSVIEW_H__A880E54F_A6EB_11D1_887F_D42B07C10710__INCLUDED_)
#define AFX_THREADSVIEW_H__A880E54F_A6EB_11D1_887F_D42B07C10710__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

UINT ThreadProcedure(LPVOID pParam);

struct SData
{
    int array[5];
    int max;
    HWND NotifyWindow;
};

class CThreadsView : public CView
{
protected: // create from serialization only
    CThreadsView();
    DECLARE_DYNCREATE(CThreadsView)

// Attributes
public:
    CThreadsDoc* GetDocument();
    SData data;
    CWinThread* Thread;
    void OnMaxFound(WPARAM wParam, LPARAM lParam);
// Operations
public:

// Overrides
    // ClassWizard generated virtual function overrides
    //{{AFX_VIRTUAL(CThreadsView)
    public:
    virtual void OnDraw(CDC* pDC);  // overridden to draw this view
    virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
    protected:
    virtual BOOL OnPreparePrinting(CPrintInfo* pInfo);
    virtual void OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo);
    virtual void OnEndPrinting(CDC* pDC, CPrintInfo* pInfo);
    //}}AFX_VIRTUAL

// Implementation
public:
    virtual ~CThreadsView();
#ifdef _DEBUG
    virtual void AssertValid() const;
    virtual void Dump(CDumpContext& dc) const;
#endif

protected:

// Generated message map functions
protected:
    //{{AFX_MSG(CThreadsView)
    afx_msg void OnFileFindmax();
    //}}AFX_MSG
    DECLARE_MESSAGE_MAP()
};

#ifndef _DEBUG  // debug version in ThreadsView.cpp
inline CThreadsDoc* CThreadsView::GetDocument()
   { return (CThreadsDoc*)m_pDocument; }
#endif

/////////////////////////////////////////////////////////////////////////////

//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately
before the previous line.

#endif // !defined(AFX_THREADSVIEW_H__A880E54F_A6EB_11D1_887F_D42B07C10710__INCLUDED_)


// ThreadsView.cpp : implementation of the CThreadsView class
//

#include “stdafx.h”
#include “Threads.h”

#include “ThreadsDoc.h”
#include “ThreadsView.h”

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif


/////////////////////////////////////////////////////////////////////////////
// CThreadsView

IMPLEMENT_DYNCREATE(CThreadsView, CView)

BEGIN_MESSAGE_MAP(CThreadsView, CView)
    //{{AFX_MSG_MAP(CThreadsView)
    ON_COMMAND(ID_FILE_FINDMAX, OnFileFindmax)
    ON_MESSAGE(WM_MAX, OnMaxFound)
    //}}AFX_MSG_MAP
    // Standard printing commands
    ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint)
    ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint)
    ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CThreadsView construction/destruction

CThreadsView::CThreadsView()
{
    // TODO: add construction code here

}

CThreadsView::~CThreadsView()
{
}

BOOL CThreadsView::PreCreateWindow(CREATESTRUCT& cs)

{
    // TODO: Modify the Window class or styles here by modifying
    //  the CREATESTRUCT cs

    return CView::PreCreateWindow(cs);
}

/////////////////////////////////////////////////////////////////////////////
// CThreadsView drawing

void CThreadsView::OnDraw(CDC* pDC)
{
    CThreadsDoc* pDoc = GetDocument();
    ASSERT_VALID(pDoc);

    pDC->TextOut(0, 0, pDoc->text);
}

/////////////////////////////////////////////////////////////////////////////
// CThreadsView printing

BOOL CThreadsView::OnPreparePrinting(CPrintInfo* pInfo)
{
    // default preparation
    return DoPreparePrinting(pInfo);
}

void CThreadsView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
    // TODO: add extra initialization before printing
}

void CThreadsView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
    // TODO: add cleanup after printing
}

/////////////////////////////////////////////////////////////////////////////
// CThreadsView diagnostics

#ifdef _DEBUG
void CThreadsView::AssertValid() const
{
    CView::AssertValid();
}

void CThreadsView::Dump(CDumpContext& dc) const
{
    CView::Dump(dc);
}

CThreadsDoc* CThreadsView::GetDocument() // non-debug version is inline
{
    ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CThreadsDoc)));
    return (CThreadsDoc*)m_pDocument;
}
#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CThreadsView message handlers

void CThreadsView::OnFileFindmax()
{
    // TODO: Add your command handler code here
    data.array[0] = 0;
    data.array[1] = 1;
    data.array[2] = 2;
    data.array[3] = 3;
    data.array[4] = 4;
    data.max = 0;

    data.NotifyWindow = m_hWnd;
    Thread = AfxBeginThread(ThreadProcedure, &data);
}

UINT ThreadProcedure(LPVOID pParam)
{
    SData* pData = (SData*)pParam;

    for(int loop_index = 0; loop_index <= 4; loop_index++){
        if(pData->array[loop_index] > pData->max)
           pData->max = pData->array[loop_index];
    }

    ::PostMessage(pData->NotifyWindow, WM_MAX, 0, 0);

    return 0;
}

void CThreadsView::OnMaxFound(WPARAM wParam, LPARAM lParam)
{
    CThreadsDoc* pDoc = GetDocument();
    ASSERT_VALID(pDoc);

    char FormattedString[100];
    wsprintf(FormattedString, “Max of the array = %d”, data.max);
    pDoc->text = FormattedString;

    TerminateThread(Thread, 0);

    Invalidate();

    return 0;
}

We’ve seen how to work with one thread, but what if we had more than one?


Previous Table of Contents Next


Products |  Contact Us |  About Us |  Privacy  |  Ad Info  |  Home

Use of this site is subject to certain Terms & Conditions, Copyright © 1996-2000 EarthWeb Inc.
All rights reserved. Reproduction whole or in part in any form or medium without express written permission of EarthWeb is prohibited. Read EarthWeb's privacy statement.