Модальный диалог с прогрессом
От: Jenyay http://jenyay.net
Дата: 22.03.05 05:15
Оценка:
Привет.

Сделал небольшой класс, чтобы запускать в потоке операцию, а в это время показывался бы модальный диалог с прогрессом.

Сам класс:
// ProgressDlg.h: interface for the CProgressDlg class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_PROGRESSDLG_H__71575EAA_918F_4B36_9063_83F9DD821DB2__INCLUDED_)
#define AFX_PROGRESSDLG_H__71575EAA_918F_4B36_9063_83F9DD821DB2__INCLUDED_

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

#include <ATLBASE.H>
#include <atlapp.h>

extern CAppModule _Module;

#include <ATLWIN.H>
#include <atlcrack.h>
#include <atlctrls.h>

#include <process.h>
#include <string>

#include "..\..\..\resource.h"

struct ProgressParam
{
    void *pParams;
    CProgressBarCtrl ProgressBar;
};

using std::string;

template<int idd> class CProgressDlg : public CDialogImpl<CProgressDlg>
{
private:
    BEGIN_MSG_MAP_EX (CAboutDlg)
        MSG_WM_INITDIALOG (OnInitDialog)
        MSG_WM_TIMER (OnTimer)
    END_MSG_MAP()

    // Aio caanu e caionoei iioie
    LRESULT OnInitDialog (HWND hwnd, LPARAM lParam)
    {
        unsigned ThreadId;
        m_FuncParams.pParams = m_pParams;
        m_FuncParams.ProgressBar = GetDlgItem(IDC_PROGRESS);

        m_FuncParams.ProgressBar.SetRange(0, 100);
        m_FuncParams.ProgressBar.SetPos (0);

        SetWindowText(m_Capture.c_str());

        m_hThread = (HANDLE)_beginthreadex(NULL, 0, (unsigned ( __stdcall * )( void * ))m_Func, 
            ((void*)(&m_FuncParams)), 0, &ThreadId);

        if (!m_hThread)
        {
            MessageBox("Ioeaea nicaaiey iioiea", "Ioeaea", MB_OK);
            return 0;
        }
        
        if (SetTimer(m_TimerId, 100) == NULL)
        {
            MessageBox("Ioeaea eieoeaeecaoee oaeia?a", "Ioeaea", MB_OK);
            return 0;
        }
        
        return 0;
    }

    // Ii oaeia?o i?iaa?yai, caaa?oeeny ee iioie
    void OnTimer (UINT TimerId, TIMERPROC proc)
    {
        if (WaitForSingleObject(m_hThread, 0) == WAIT_OBJECT_0)
        {
            // Anee iioie ia ?aaioaao, cae?uaaai aeaeia
            
            KillTimer(m_TimerId);
            EndDialog(0);
        }
    }

    
    int m_TimerId;
    
    HANDLE m_hThread;
    LPTHREAD_START_ROUTINE m_Func;
    void *m_pParams;
    string m_Capture;

    // Eiaiii yoi ia?aaaai a ooieoe? iioiea, a ia oa a?aoiaiou, eioi?ue void*
    ProgressParam m_FuncParams;
public:
    CProgressDlg(LPTHREAD_START_ROUTINE func, void* params, char *capture): m_Func (func), 
        m_TimerId(101), m_hThread(0), m_pParams (params), m_Capture (capture)
    {
    }
    
    virtual ~CProgressDlg()
    {
    }

    void Start()
    {
        DoModal();
    }

    enum { IDD = idd };
};



Пример использования:

LRESULT CMainWindow::OnProgress(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
{
    CProgressDlg<IDD_PROGRESS> dlg (ThreadProc, NULL, "I?ia?ann");
    dlg.Start();
    
    return 0;
}

DWORD WINAPI CMainWindow::ThreadProc (void* params)
{
    ProgressParam *pp = (ProgressParam*)params;

    for (int i = 0; i < 100; ++i)
    {
        Sleep (100);
        pp->ProgressBar.SetPos(i);
    }
    return 0;
}
... << RSDN@Home 1.1.4 beta 4 rev. 0>>
Софт, исходники и фото
Re: Модальный диалог с прогрессом
От: Jenyay http://jenyay.net
Дата: 24.03.05 06:00
Оценка:
Тут оказывается забыл удалить хендл потока, когда он не нужен и только сейчас заметил, что с комментариями что-то произошло

Вот правильная версия:

// ProgressDlg.h: interface for the CProgressDlg class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_PROGRESSDLG_H__71575EAA_918F_4B36_9063_83F9DD821DB2__INCLUDED_)
#define AFX_PROGRESSDLG_H__71575EAA_918F_4B36_9063_83F9DD821DB2__INCLUDED_

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

#include <ATLBASE.H>
#include <atlapp.h>

extern CAppModule _Module;

#include <ATLWIN.H>
#include <atlcrack.h>
#include <atlctrls.h>

#include <process.h>
#include <string>

#include "..\..\..\resource.h"

struct ProgressParam
{
    void *pParams;
    CProgressBarCtrl ProgressBar;
};

using std::string;

template<int idd> class CProgressDlg : public CDialogImpl<CProgressDlg>
{
private:
    BEGIN_MSG_MAP_EX (CAboutDlg)
        MSG_WM_INITDIALOG (OnInitDialog)
        MSG_WM_TIMER (OnTimer)
    END_MSG_MAP()

    // Вот здесь и запустим поток
    LRESULT OnInitDialog (HWND hwnd, LPARAM lParam)
    {
        unsigned ThreadId;
        m_FuncParams.pParams = m_pParams;
        m_FuncParams.ProgressBar = GetDlgItem(IDC_PROGRESS);

        m_FuncParams.ProgressBar.SetRange(0, 100);
        m_FuncParams.ProgressBar.SetPos (0);

        SetWindowText(m_Capture.c_str());

        m_hThread = (HANDLE)_beginthreadex(NULL, 0, (unsigned ( __stdcall * )( void * ))m_Func, 
            ((void*)(&m_FuncParams)), 0, &ThreadId);

        if (!m_hThread)
        {
            MessageBox("Ошибка создания потока", "Ошибка", MB_OK);
            return 0;
        }
        
        if (SetTimer(m_TimerId, 100) == NULL)
        {
            MessageBox("Ошибка инициализации таймера", "Ошибка", MB_OK);
            return 0;
        }
        
        return 0;
    }

    // По таймеру проверяем, завершился ли поток
    void OnTimer (UINT TimerId, TIMERPROC proc)
    {
        if (WaitForSingleObject(m_hThread, 0) == WAIT_OBJECT_0)
        {
            // Если поток не работает, закрываем диалог
            
            KillTimer(m_TimerId);
            CloseHandle(m_hThread);
            EndDialog(0);
        }
    }

    
    int m_TimerId;
    
    HANDLE m_hThread;
    LPTHREAD_START_ROUTINE m_Func;
    void *m_pParams;
    string m_Capture;

    // Именно это передаем в функцию потока, а не те аргументы, который void*
    ProgressParam m_FuncParams;
public:
    CProgressDlg(LPTHREAD_START_ROUTINE func, void* params, char *capture): m_Func (func), 
        m_TimerId(101), m_hThread(0), m_pParams (params), m_Capture (capture)
    {
    }
    
    virtual ~CProgressDlg()
    {
    }

    void Start()
    {
        DoModal();
    }

    enum { IDD = idd };
};

#endif // !defined(AFX_PROGRESSDLG_H__71575EAA_918F_4B36_9063_83F9DD821DB2__INCLUDED_)
... << RSDN@Home 1.1.4 beta 4 rev. 0>>
Софт, исходники и фото
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.