Multiple threads in MFC

zhaozj2021-02-08  261

Multiple threads in MFC

-------------------------------------------------- -----------------------------

I tried to express the concept of threads with self, there is a small sample program compiled in a short time (I don't know if it is right, I don't know if I can say it ..), I laugh.

Thread actually and the standard Windows main program (WinMain) is not a two ... The main program is actually a special thread, called the main thread, in fact, you can do the thread to be integrated with WinMain. ** But ** can access some small Winmain programs (ie in an address space) **. Like the main thread, you can create a window, get a message, and more ..

Since the threads are running at an address space, it will cause some trouble. Because we have programmed the library of others, and their library often has a lot of static or global status or intermediate variables, there is a complex mutual dependency, if a function is not serialized (so-called string It is to train, that is, only one function call is returned, another thread can call, can not call at the same time, will cause chaos. This is a thread, and the term is synchronized. Windows provides us with a lot of synchronization. Methods, MFC also provides some classification of synchronous core objects. For a feature call library, call thread security. For example, the MFC class library is not a thread.

Now I will give an example of just a self-organizing example. One of the following dialog applications is multithreaded. Demo two small animations:

(1) The first animation is driven by the main thread Timer. The second animation is driven by the working thread created by the main line. Displayed in different locations, and I want to join Timer, and to form thread drivers and Timer Drive control, this is the two driving methods of animation (also driven in idle).

(2) These two animations will always be different. This is, for example, one is crying, one will smile, wait for that smile, this is crying. The animation picture comes from the Face directory in OICQ, general The same avatar will take three pictures (* -1.bmp, * - 2.bmp, * - 3.bmp), * - 2.BMP is a gray picture, I will take pictures of 1 and 3 To make animations.

Several key to this program pay attention to:

(1) The main thread uses PostthreadMessage and work thread communication. Work thread Use PeekMessage to retrieve the message. For simplicity, I only use a WM_QUIT message to indicate the work thread exits.

(2) The main thread and the working thread simultaneously call a DisplayFace function to make an animation display. In order to make two animation crying and smile, using ccriticalsection to synchronize.

Examples are as follows:

(1) First Generate an MFC Dialog Application Template with AppWizards, assume that the dialog box is CTEST01DLG.

(2) Add two OICQ's BMP files to resources.

(3) Add a button (Button) to the dialog box. Used as startup, stop the animation of Button

(4) Generate event response functions with ClassWizard to Button / OnClick and DLG / ONTIMER,

(5) Add a logo definition IDC_TIMER1 with Resource Symbol

(6) Add the following member variables and member functions to CTEST01DLG in ClassView.

Criticalsection CCS;

CBITMAP BM [2];

CWINTHREAD * PMYTHREAD;

Static uint mythreadproc (lpvoid pparam);

Void DisplayFace (CPOINT R);

Add corresponding code in the implementation file (see below)

(7) Add #include in stdafx.h

The source code is as follows, and every surprise surrounded by my new code is surrounded by ClassWizards.

// stdafx.h: include File for Standard System Include Files,

// or project specificin files That Are Used Frequently, But // Are Changed Infrequently

File: //

#if! defined (afX_STDAFX_H__5B92DAA8_FE27_4702_8037_A2538343E69D__included_)

#define AFX_STDAFX_H__5B92DAA8_FE27_4702_8037_A2538343E69D__included_

#iF _MSC_VER> 1000

#pragma overce

#ENDIF / / 100 m _ _

#define vc_extralean // Exclude Rarely-usest Stuff from Windows Headers

#include // MFC Core and Standard Components

#include // mfc extensions

#include // MFC Support for Internet Explorer 4 Common Controls

File: // The joining header is mainly defined by the CcriticalSection object.

#include

File: // Add to end

#ifndef _AFX_NO_AFXCMN_SUPPORT

#include // MFC Support for Windows Common Controls

#ENDIF / / _AFX_NO_AFXCMN_SUPPORT

File: // {{{AFX_INSERT_LOCATION}}}

// Microsoft Visual C Will Insert Additional Declarations Immediate Line.

#ENDIF /! Defined (AFX_STDAFX_H__5B92DAA8_FE27_4702_8037_A2538343E69D__included_)

// Test01dlg.h: Header File

File: //

#if! defined (AFX_TEST01DLG_H__F3780E23_CCFC_468C_A262_50FFF1D991BC__INCLUDED_)

#define AFX_TEST01DLG_H__F3780E23_CCFC_468C_A262_50FFF1D991BC__INCLUDED_

#iF _MSC_VER> 1000

#pragma overce

#ENDIF / / 100 m _ _

/

// ctest01dlg dialog

Class ctest01dlg: public cdialog

{

// construction

PUBLIC:

File: // Join

CBITMAP BM [2];

CcriticalSECTION CCS;

CWINTHREAD * PMYTHREAD;

Static uint mythreadproc (lpvoid pparam);

Void DisplayFace (CPOINT R);

CTEST01DLG (CWND * PParent = null); // Standard Constructionor

File: // Add to end

// Dialog Data

FILE: / / {{AFX_DATA (CTEST01DLG)

ENUM {IDD = IDD_TEST01_DIALOG};

// Note: The Classwizard Will Add Data MEMBERS Here

File: //}} AFX_DATA

// ClassWizard Generated Virtual Function Overrides

File: // {{AFX_VIRTUAL (CTEST01DLG)

protected:

Virtual Void DodataExchange (CDataExchange * PDX); // DDX / DDV Support

File: //}} AFX_VIRTUAL

// Implementation

protected:

Hicon M_Hicon;

// generated message map functions

File: // {{{AFX_MSG (CTEST01DLG)

Virtual Bool OnInitdialog ();

AFX_MSG Void OnSysCommand (Uint Nid, LParam Lparam);

AFX_MSG void onpaint ();

AFX_MSG HCURSOR ONQUERYDRAGICON ();

AFX_MSG void onbutton1 ();

AFX_MSG Void Ontimer (uint nidEvent);

File: //}} AFX_MSG

Declare_message_map ()

}

File: // {{{AFX_INSERT_LOCATION}}}

// Microsoft Visual C Will Insert Additional Declarations Immediate Line.

#endif //! defined (AFX_TEST01DLG_H__F3780E23_CCFC_468C_A262_50FFF1D991BC__INCLUDED_)

// TEST01DLG.CPP: Implementation File

File: //

#include "stdafx.h"

#include "test01.h"

#include "test01dlg.h"

#ifdef _Debug

#define new debug_new

#undef this_file

Static char this_file [] = __file__;

#ENDIF

/

// Caboutdlg Dialog Used for App About

Class Caboutdlg: Public CDIALOG

{

PUBLIC:

Caboutdlg ();

// Dialog Data

File: // {{AFX_DATA (Caboutdlg)

Enum {IDD = IDD_ABOUTBOX};

File: //}} AFX_DATA

// ClassWizard Generated Virtual Function Overrides

File: // {{{AFX_VIRTUAL (Caboutdlg)

protected:

Virtual Void DodataExchange (CDataExchange * PDX); // DDX / DDV Support

File: //}} AFX_VIRTUAL

// Implementation

protected:

File: // {{{AFX_MSG (Caboutdlg)

File: //}} AFX_MSG

Declare_message_map ()

}

Caboutdlg :: Caboutdlg (): cdialog (Caboutdlg :: IDD)

{

File: // {{AFX_DATA_INIT (Caboutdlg)

File: //}} AFX_DATA_INIT

}

Void Caboutdlg :: DODATAEXCHANGE (CDataExchange * PDX)

{

CDIALOG :: DODATAEXCHANGE (PDX);

FILE: / / {{{AFX_DATA_MAP (Caboutdlg)

File: //}} AFX_DATA_MAP

}

Begin_MESSAGE_MAP (Caboutdlg, CDIALOG)

File: // {{AFX_MSG_MAP (Caboutdlg) // No Message Handlers

File: //}} AFX_MSG_MAP

END_MESSAGE_MAP ()

/

// ctest01dlg dialog

CTEST01DLG :: CTEST01DLG (CWND * PParent / * = NULL * /)

: Cdialog (ctest01dlg :: IDd, pparent)

{

File: // {{AFX_DATA_INIT (CTEST01DLG)

// Note: The classwizard will add member initialization here

File: //}} AFX_DATA_INIT

// Note That Loadicon Does Not Require a Subsequent Destroyicon in Win32

m_hicon = AFXGetApp () -> loadicon (iDR_mainframe);

File: // Join

PMYTHREAD = NULL;

File: // Add to end

}

Void ctest01dlg :: DODATAEXCHANGE (CDataExchange * PDX)

{

CDIALOG :: DODATAEXCHANGE (PDX);

FILE: / / {{{AFX_DATA_MAP (CTEST01DLG)

// Note: The Classwizard Will Add Ddx and DDV Calls Here

File: //}} AFX_DATA_MAP

}

Begin_MESSAGE_MAP (CTEST01DLG, CDIALOG)

File: // {{AFX_MSG_MAP (CTEST01DLG)

ON_WM_SYSCOMMAND ()

ON_WM_PAINT ()

ON_WM_QUERYDRAGICON ()

ON_BN_CLICKED (IDC_Button1, Onbutton1)

ON_WM_TIMER ()

File: //}} AFX_MSG_MAP

END_MESSAGE_MAP ()

/

// ctest01dlg Message Handlers

BOOL CTEST01DLG :: OnItDialog ()

{

CDIALOG :: OnInitdialog ();

// Add "About ..." Menu Item to System Menu.

// IDM_AboutBox Must Be in The System Command Range.

Assert (IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);

Assert (IDM_AboutBox <0xf000);

CMenu * psysmenu = getSystemMenu (false);

IF (psysmenu! = NULL)

{

CSTRING STRABOUTMENU;

STRABOUTMENU.LOADSTRING (IDS_ABOUTBOX);

IF (! straboutmenu.isempty ())

{

Psysmenu-> appendmenu (mf_separator);

Psysmenu-> appendmenu (mf_string, idm_aboutbox, straboutmenu);

}

}

// set the icon for this dialog. The framework does this AutomaticL

// when the application ''s main window is not a dialog

Seticon (M_Hicon, True); // set Big icon

Seticon (M_Hicon, False); // set small icon

// Todo: Add Extra Initialization Here

File: // Join

BM [0] .loadBitmap (idb_bitmap1);

BM [1] .loadBitmap (IDB_bitmap3);

File: // Add to end

Return True; // Return True UnsS you set the focus to a control

}

Void ctest01dlg :: oversyscommand (uint nid, lparam lparam)

{

IF ((NID & 0xFFF0) == IDM_ABOUTBOX)

{

Caboutdlg dlgabout;

DLGAbout.domodal ();

}

Else

{

CDIALOG :: OnSysCommand (NID, LPARAM);

}

}

Void ctest01dlg :: onpaint ()

{

IF (Isiconic ())

{

CPAINTDC DC (this); // Device Context for Painting

SendMessage (WM_ICONERASEBKGND, (WPARAM) dc.getsafehdc (), 0);

// Center icon in Client Rectangle

INT CXCION = GetSystemMetrics (SM_CXICON);

INT Cyicon = GetSystemMetrics (SM_CYICON);

CRECT RECT;

GetClientRect (& RECT);

INT x = (Rect.width () - CXICON 1) / 2;

INT Y = (Rect.height () - Cyicon 1) / 2;

// Draw the icon

Dc.drawicon (X, Y, M_HICON);

}

Else

{

CDIALOG :: onpaint ();

}

}

Hcursor ctest01dlg :: ONQUERYDRAGICON ()

{

Return (hcursor) m_hicon;

}

File: // Join

Void ctest01dlg :: onbutton1 ()

{

Static bool bstarted = false;

IF (! bstarted) {

Settimer (IDC_TIMER1, 500, NULL);

PMYTHREAD = AFXBEGINTHREAD (MythreadProc, this);

} else {

IF (PMYTHREAD) {

PMYTHREAD-> PostthreadMessage (wm_quit, 0,0);

:: WaitforsingleObject (PMYTHREAD-> M_HTHREAD, INFINITE);

PMYTHREAD = NULL;

}

KillTimer (IDC_TIMER1);

}

Bstarted =! bstarted;

((Cbutton *) getdlgitem (idc_button1)) -> setWindowText ((bstarted? _T ("stop"): _ t ("start")));

}

Void ctest01dlg :: ONTIMER (uint nidevent)

{

IF (nidevent == idc_timer1)

DisplayFace (CPOINT (10, 10));

CDIALOG :: ONTIMER (Nidevent);

}

Void ctest01dlg :: DisplayFace (cpoint p)

{

Static I = 0;

CCS.LOCK ();

Bitmap bmo;

BM [I] .GetObject (Sizeof (BMO), & BMO; CClientDC DC (this);

CDC BMPDC;

BMPDC.CREATECOMPALEDC (& DC);

BMPDC.SELECTOBJECT (& BM [i]);

DC.Bitblt (P.x, P.Y, BMo.bmwidth, Bmo.bmheight, & BMPDC, 0, 0, SRCCPY);

i ;

IF (i == sizeof (bm) / sizeof (BM [0])) i = 0;

CCS.unlock ();

}

Uint ctest01dlg :: MythreadProc (lpvoid pparam)

{

CTEST01DLG * ME = (CTEST01DLG *) PPARAM;

MSG msg;

While (! PeekMessage (& MSG, NULL, 0, 0, PM_NOREMOVE) {

ME-> DisplayFace (CPOINT (100, 10));

:: Sleep (200);

}

Return 0;

}

File: // Add to end

转载请注明原文地址:https://www.9cbs.com/read-1722.html

New Post(0)