📄 gdithread.cpp
字号:
//this file is part of eMule
//Copyright (C)2002 Merkur ( devs@emule-project.net / http://www.emule-project.net )
//
//This program is free software; you can redistribute it and/or
//modify it under the terms of the GNU General Public License
//as published by the Free Software Foundation; either
//version 2 of the License, or (at your option) any later version.
//
//This program is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
//GNU General Public License for more details.
//
//You should have received a copy of the GNU General Public License
//along with this program; if not, write to the Free Software
//Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#include "stdafx.h"
#include "GDIThread.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
// critical section to protect while drawing to the DC
CCriticalSection CGDIThread::m_csGDILock;
// m_hAnotherDead is used to signal that one or more threads have ended
// (it is an auto-reset event; and starts out not signaled)
//HANDLE CGDIThread::m_hAnotherDead = CreateEvent(NULL, FALSE, FALSE, NULL);
/////////////////////////////////////////////////////////////////////////////
// CGDIThread
IMPLEMENT_DYNAMIC(CGDIThread, CWinThread)
BEGIN_MESSAGE_MAP(CGDIThread, CWinThread)
//{{AFX_MSG_MAP(CGDIThread)
// NOTE - the ClassWizard will add and remove mapping macros here.
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
CGDIThread::CGDIThread(CWnd* pWnd, HDC hDC)
{
m_bAutoDelete = FALSE;
m_pMainWnd = pWnd;
m_hDC = hDC;
m_nDelay = 50;
m_nScrollInc = SCROLL_UP;
m_bWaitVRT = FALSE;
// kill event starts out in the signaled state
m_hEventKill = CreateEvent(NULL, TRUE, FALSE, NULL);
m_hEventDead = CreateEvent(NULL, TRUE, FALSE, NULL);
}
// The reason we don't just get a CDC from our owner and simply use it is because
// MFC GDI objects can't be passed between threads. So we must instead pass a
// handle and then reconvert them back to MFC objects. The reason for this is
// because MFC maintains a list of all GDI objects on a per thread basis. So if
// you pass a GDI object to another thread, it won't be in the correct list
// and MFC will assert.
BOOL CGDIThread::InitInstance()
{
// thread setup
m_dc.Attach(m_hDC);
// loop but check for kill notification
while (WaitForSingleObject(m_hEventKill, 0) == WAIT_TIMEOUT)
SingleStep();
// thread cleanup
m_dc.Detach();
// avoid entering standard message loop by returning FALSE
return FALSE;
}
void CGDIThread::Delete()
{
// calling the base here won't do anything but it is a good habit
CWinThread::Delete();
// acknowledge receipt of kill notification
VERIFY(SetEvent(m_hEventDead));
//VERIFY(SetEvent(m_hAnotherDead)); // what is this good for? nobody is waiting on that event!
}
CGDIThread::~CGDIThread()
{
CloseHandle(m_hEventKill);
CloseHandle(m_hEventDead);
//CloseHandle(m_hAnotherDead);
}
void CGDIThread::KillThread()
{
// Note: this function is called in the context of other threads,
// not the thread itself.
// reset the m_hEventKill which signals the thread to shutdown
VERIFY(SetEvent(m_hEventKill));
// allow thread to run at higher priority during kill process
SetThreadPriority(THREAD_PRIORITY_ABOVE_NORMAL);
WaitForSingleObject(m_hEventDead, INFINITE);
WaitForSingleObject(m_hThread, INFINITE);
// now delete CWinThread object since no longer necessary
delete this;
}
/////////////////////////////////////////////////////////////////////////////
// CGDIThread message handlers
int CGDIThread::SetDelay(int nDelay)
{
int nTmp = m_nDelay;
m_nDelay = nDelay;
return nTmp;
}
int CGDIThread::SetScrollDirection(int nDirection)
{
int nTmp = m_nScrollInc;
m_nScrollInc = nDirection;
return nTmp;
}
BOOL CGDIThread::SetWaitVRT(BOOL bWait)
{
BOOL bTmp = m_bWaitVRT;
m_bWaitVRT = bWait;
return bTmp;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -