|
Hi,
I have a class
class CTestDlg : public CDialog , public D360::CController
{
which I want to respond to messages like
BEGIN_MESSAGE_MAP(CTestDlg, CDialog)
ON_MESSAGE(OLDA_WM_BUFFER_DONE, OnBufferDone)
END_MESSAGE_MAP()
This worked when the CTestDlg class only inherited from CDialog, but now I get the following compilation error
error C2440: 'type cast' : cannot convert from 'int (__thiscall CTestDlg::*)(unsigned int,long)' to 'long (__thiscall CWnd::*)(unsigned int,long)'
Pointers to members have different representations; cannot cast between them
I don't know much about the D360::CController class, it was supplied with some hardware.
Any suggestions would be appreciated.
Will
|
|
|
|
|
Do you really have to derive from D360::CController? Are there any CController virtual functions you are overriding?
Tomasz Sowinski -- http://www.shooltz.com
What is "scratch" and why can everything be made from it?
|
|
|
|
|
As far as I can tell, yes I do have to derive from D360::CController - it is doing something I don't understand with ATL to interface with the hardware. The only example code the company sent me used multiple inheritance.
Is this a general problem with ON_MESSAGE and multiple inheritance, or just a strange quirk of the classes I am trying to inherit from?
Will
|
|
|
|
|
Will Woods wrote:
Is this a general problem with ON_MESSAGE and multiple inheritance, or just a strange quirk of the classes I am trying to inherit from?
Well, the MFC wasn't designed with multiple inheritance in mind. This means that you can't have your object derived from CCoolWnd and COtherWnd. OTOH, you can derive your object from CWnd (or CView, CDialog, or any other MFC window class) and non-MFC class[es]. In such case you just have to make sure that MFC class is first in the base classes list. I've used this approach in many MFC-based projects.
So one possible reason for your problems would be CController deriving from some MFC class. Can you have a look on the D360 docs?
Tomasz Sowinski -- http://www.shooltz.com
What is "scratch" and why can everything be made from it?
|
|
|
|
|
Problem solved - I had declared the callback functions to return bool (as 'required' by some other hardware drivers) - changing the return type to LRESULT fixed the problem.
I wonder why this compiled ok (I just checked it, it does) before I added the second inheritance??
Thanks for your help.
Will
|
|
|
|
|
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;
}
|
|
|
|