|
I am reading a book on the GDI and have noticed that the author deletes an object before reusing it but do not delete it before restoring the 'Old Object'. Why is this? Is it good practise to delete the object anyway, after reselecting the 'Old Object'?
|
|
|
|
|
If object is selected into device context, the call to DeleteObject fails.
So, if you don't select 'old' object or any other existing object of given type, you'll get GDI memory leak.
Your other option is to destroy DC first; this will release all objects. However, this isn't always possible. For example, CView::OnDraw method gets the DC as parameter and you shouldn't destroy this context.
Another solution could be using SaveDC and RestoreDC functions.
Tomasz Sowinski -- http://www.shooltz.com
What is "scratch" and why can everything be made from it?
|
|
|
|
|
But is there a good reason why the author is not deleting his objects after reselecting the 'OldObject'(by this I mean the windows pen or font that was being used before my program started creating objects)? Does selecting the 'OldObject' automatically delete the existing object? Or is he a nitwit ?;P and I do have to delete any object I create regardless of whether I Reselect the 'OldObject'
|
|
|
|
|
Anonymous wrote:
But is there a good reason why the author is not deleting his objects after reselecting the 'OldObject'
It depends. If he's using MFC, then CPen/CBrush/CFont destructor will call DeleteObject. Since object isn't selected anymore, the DeleteObject will succeed.
He also may be using global variables or class members with lifetime longer than piece of code in which he's using GDI objects
But - if he's running on raw Win32 API and there are no DeleteObject calls for local objects created with CreatePen/Brush/Font etc., then he is a nitwit indeed. BTW: who's 'the author'?
Tomasz Sowinski -- http://www.shooltz.com
What is "scratch" and why can everything be made from it?
|
|
|
|
|
He is using MFC and since chances that I'm the nitwit is rather big, and he has a great sense of humour, I will refrain from mentioning any names. Thanks for the answer it was just what I needed to know
|
|
|
|
|
I want to use CreateThread() function, and i have created a ThreadFunc. The problem is, that i want this ThreadFunc to be placed within a calss (i don't want it to be a global function).
member function is defined as follows:
<br />
unsigned long __stdcall ThreadFunc(void * Parameter);<br />
And i try to do a conversion to:
<br />
LPTHREAD_START_ROUTINE TS;<br />
Both:
<br />
TS=ThreadFunc;<br />
And:
<br />
TS=CMyDialog::ThreadFunc;<br />
Report as follows:
error C2440: '=' : cannot convert from
'unsigned long (__stdcall CMyDialog::*)(void *)'
to
'unsigned long (__stdcall *)(void *)'
First conversion works when ThreadFunc is not a class member, but both fails when it is a class member.
How to make this conversion?
Railgun is like a Gilette Mach 3 - it does the job with one, easy stroke.
|
|
|
|
|
If you insist on member function, you must make it a static one. Also, if you use CreateThread, you may hit problems with C++ runtime. Use _beginthread[ex]; these functions call CreateThread for you.
Tomasz Sowinski -- http://www.shooltz.com
What is "scratch" and why can everything be made from it?
|
|
|
|
|
Adding to what Tomasz said, use only the _beginthreadex(do not use _beginthread or CreateThread) or AfxBeginThread in MFC, these 2 functions create the necessary TIB(Thread Information Block) that is necessary to the C/C++ runtime could correctly dispose and control the Thread specific data.
Cheers,
Joao Vaz
And if your dream is to care for your family, to put food on the table, to provide them with an education and a good home, then maybe suffering through an endless, pointless, boring job will seem to have purpose. And you will realize how even a rock can change the world, simply by remaining obstinately stationary. - Shog9
|
|
|
|
|
Thank you for an advise.
Using static function was the key problem. Now it works fine.
By the way - what kind of runtime problems may occur when using CreateThread?
I've been using this one many times, and never had problems with managing threads.
[ CoY0te ]
Railgun is like a Gilette Mach 3 - it does the job with one, easy stroke.
|
|
|
|
|
Check this article for discussion of CreateThread vs AfxBeginThread vs _beginthreadex:
http://www.microsoft.com/msj/defaulttop.asp?page=/msj/archive/S39CD.htm[^]
Heer's an interesting excerpt:
Don't create threads with the C runtime functions beginthread or beginthreadex if the threads will access any MFC objects. The framework uses CWinThread to manage thread-specific data. You should use AfxBeginThread to start your threads (or call the CWinThread constructor and its CreateThread method). CWinThread::CreateThread eventually calls beginthreadex after taking care of some setup and synchronization
Tomasz Sowinski -- http://www.shooltz.com
What is "scratch" and why can everything be made from it?
|
|
|
|
|
Even while thread functions follow the calling conventions of a standard C function and therfore have to be static functions, it is not impossible to create a thread directly in a member function. The key to do this is utilizing adapter objects, that translate the C-stylish callback into a call to a member function.
This is explained in detail in the article Use member functions for C-style callbacks and threads - a general solution. Using the techiques described there, creating threads becomes real fun:
#include "stdafx.h"
#include "win_adapter.h"
class Test
{
public:
virtual DWORD ThreadStart( LPCTSTR pszName )
{
printf( " Hello, I'm a Thread and my name is: %s\n", pszName );
return 0;
}
};
void main()
{
Test test;
LPCTSTR pszThreadName = "Joe, the funny thread";
HANDLE hThread = win::beginthreadex( &test, &Test::ThreadStart, pszThreadName );
WaitForSingleObject( hThread, INFINITE );
CloseHandle( hThread );
}
Of course this makes live and code a lot nicer, because you don't have to write all those static wrappers including ugly casts and so on. And the best thing is, that all you need to use it is to include one single header file! No CPP file to add to your project, no libs, no interface or class to derive from, no structural dependencies at all.
(Ehm, yes... I am a bit proud about this piece of code )
--
Daniel Lohmann
http://www.losoft.de
(Hey, this page is worth looking! You can find some free and handy NT tools there )
|
|
|
|
|
Daniel Lohmann wrote:
no interface or class to derive from, no structural dependencies at all.
So why Test::ThreadStart is virtual? Please note that I haven't read your article yet. Can you explain in 25 words or less?
Tomasz Sowinski -- http://www.shooltz.com
What is "scratch" and why can everything be made from it?
|
|
|
|
|
Tomasz Sowinski wrote:
So why Test::ThreadStart is virtual? Please note that I haven't read your article yet. Can you explain in 25 words or less?
Ehm, just to show that it is possible to use even virtual functions as thread starters. However, it does not have to be virtual. It just a member function.
(Oh, sorry, that's about 33 words )
--
Daniel Lohmann
http://www.losoft.de
(Hey, this page is worth looking! You can find some free and handy NT tools there )
|
|
|
|
|
Thanks - looks really nice indeed.
Anyway, I don't need any serious thread managment at this time, and I don't store the thread handle at all. I just have to run it and wait till it finishes the job, but I don't have to wait till process it really quits. All I care is when the data will be ready.
[ CoY0te ]
Railgun is like a Gilette Mach 3 - it does the job with one, easy stroke.
|
|
|
|
|
Okay, if your stuff works right now you have no reason to change it
However, please note that the described technique has nothing to do with "serious thread management". It just shows how to use member functions where C-style callbacks are expected. This is exactly what you asked in your original post: How to do the conversion from a pointer to a member function to THREAD_START_ROUTINE
--
Daniel Lohmann
http://www.losoft.de
(Hey, this page is worth looking! You can find some free and handy NT tools there )
|
|
|
|
|
Can we create a bitmap of a hidden window??????
|
|
|
|
|
You may try to send WM_PRINT. Just remember that window is free to ignore this message.
Tomasz Sowinski -- http://www.shooltz.com
What is "scratch" and why can everything be made from it?
|
|
|
|
|
hi !!!
can u plz tell me how to calculate the total duration of an audio file using VC++ (or SDK).....
u can also contact me at jayostu@yahoo.com
bye
jayostu
|
|
|
|
|
The code below is a simple pool manager i written for pooling the VBScript
engines. I also created a CShirleyScriptSite COM:
<br />
class ATL_NO_VTABLE CShirleyScriptSite :<br />
public CComObjectRootEx<CComMultiThreadModel>,<br />
public CComCoClass<CShirleyScriptSite, &CLSID_ShirleyScriptSite>,<br />
public IDispatchImpl<IShirleyScriptSite, &IID_IShirleyScriptSite,<br />
&LIBID_ShirleyLib, 1, 0>,<br />
public IActiveScriptSiteImpl,<br />
public IActiveScriptSiteWindowImpl<br />
{<br />
... ...<br />
}<br />
I put into a MFC application 's MainFrame,
CComPoolManager<CComObject<cshirleyscriptsite> >="" m_scriptegr_pool;
in="" init="" instance,="" i="" called="" m_scriptegr_pool.createpoolobjects().="" when="" the
mainframe="" is
displayed,="" click="" the="" "x"="" button,="" then="" application="" should="" exits.
however,="" it="" is
still="" "run"="" in="" debugger,="" and="" ccompoolmanager's="" destructor="" seemed="" not
to="" be="" called.
anything="" wrong="" ?
if="" don't="" add="" line="" m_scriptegr_pool.createpoolobjects(),="" exits="" to
[design]="" mode
normally.="" can="" anyone="" show="" me="" night="" ?
<code="">
////////////////////////////////////////////////////////////////////////////
///////////////
//Function: CComPoolManager
//
//Description: A pool manager that does pooling of COM Objects. The
controlled objects (T)
// must be derived from CComObject<TypeName>.
//
//Usage: CComPoolManager<CComObject<CYourComClass> > m_my_pool;
////////////////////////////////////////////////////////////////////////////
///////////////
template <class T, int PZ = 10>
class CComPoolManager
{
public:
typedef std::deque<T*>::iterator iterator;
CComPoolManager() : m_pool_threshold(PZ)
{
TRACE("CComPoolManager constructor called\n");
InitializeCriticalSection(&m_cs);
}
~CComPoolManager()
{
TRACE("CComPoolManager destructor called\n");
iterator itr;
for(itr=m_free_list.begin();itr!=m_free_list.end();itr++)
{
(*itr)->Release();
}
m_free_list.clear();
DeleteCriticalSection(&m_cs);
}
//create default no. of objects
void CreatePoolObjects(int sz = PZ)
{
if (sz > PZ)
sz = PZ;
while(m_free_list.size() < sz)
{
T* pobj = NULL;
HRESULT hRes = T::CreateInstance(&pobj);
_ASSERTE(SUCCEEDED(hRes));
m_free_list.push_back(pobj);
}
}
void SetPoolThreshold(long thr)
{
m_pool_threshold = thr;
}
T* AllocateFromPool()
{
T* pobj = NULL;
EnterCriticalSection(&m_cs);
//allocate from the beginning of the list
iterator itr = m_free_list.begin();
if (itr != m_free_list.end())
{
pobj = *itr;
m_free_list.pop_front();
}
else
{
HRESULT hRes = T::CreateInstance(&pobj);
_ASSERTE(SUCCEEDED(hRes));
}
LeaveCriticalSection(&m_cs);
return pobj;
}
void ReturnToPool(T* pobj)
{
EnterCriticalSection(&m_cs);
if (m_free_list.size() > m_pool_threshold)
{
pobj->Release();
}
else
{
m_free_list.push_back(pobj);
}
LeaveCriticalSection(&m_cs);
}
private:
CRITICAL_SECTION m_cs;
std::deque<T*> m_free_list;
long m_pool_threshold;
};
|
|
|
|
|
Hi there,
I need to send a message to a UDP or TCP client.
The function needs to be synchronic.
I the following code 'good practice' ?
When does Send() or SendTo() return WSAEWOULDBLOCK ?
Greetings,
Niko
bool CSomeClass::SendMessage(BYTE *lpBuf, int iBufLen)
{
if (GetConnectionType() == eTCP)
{
if(!m_pSocket)
return false;
int iBytesSend = 0;
while (iBytesSend < iBufLen)
{
iBytesSend += m_pSocket->Send(lpBuf+iBytesSend, iBufLen-iBytesSend);
if (iBytesSend == SOCKET_ERROR)
return false;
}
return true;
}
else if (GetConnectionType() == eUDP)
{
//Use Server socket to send UDP Message
int iBytesSend = 0;
while (iBytesSend < iBufLen)
{
iBytesSend += m_pServerSocketUDP->SendTo(lpBuf+iBytesSend, iBufLen-iBytesSend,
m_uiPeerPortConnection, m_csPeerNameConnection);
if (iBytesSend == SOCKET_ERROR)
return false;
}
return true;
}
return false;
}
|
|
|
|
|
Is the socket actually connected when you send this call?
STL is a religeon. Enquiries to Reverend Christian Graus
|
|
|
|
|
Jon Hulatt wrote:
Is the socket actually connected when you send this call?
Yes,
TCP socket is accepted.
UDP socket is ready to send/receive
|
|
|
|
|
Hello, the codegurus around the world.;)
Actually, does your code work for both UDP and TCP client?
Did you change the port number for UDP or TCP client?
I believe that one server can create the socket with both UDP and TCP,
but the server have to change the port number.
WSAEWOULDBLOCK message is called on non-blocking and asyncrious socket.
So, if you use blocking or syncrious socket, WSAEWOULDBLOCK is never called.
As long as you use Asyncsocket class, WSAEWOULDBLOCK might be called at any time.
Please, don't send me your email about your questions directly.
Have a nice day!
Sonork - 100.10571:vcdeveloper
-Masaaki Onishi-
|
|
|
|
|
Hi,
How can I find out the value of CLOCKS_PER_SEC?
Best regards/ Janette
|
|
|
|
|
It's defined in Time.h and it's value is 1000.
By the way - using windows timer is sometimes not enough.
Although CLOCKS_PER_SEC is 1000, the timer is updated approximately every 55ms, that is less than 20 times per second.
As for me i prefer to use QueryPerformanceCounter and QueryPerformanceFrequency functions - these use a timer that is updated very often (depends on hardware). I should be "smoother" than 1us (over 1MHz frequency).
Railgun is like a Gilette Mach 3 - it does the job with one, easy stroke.
|
|
|
|