|
The statement "delete this" is amusing. I always add the comment "// hari kari".
Anyway, common practice is to keep a pointer to the modeless dialog in the object that creates it so you can just bring it forward if it is reinvoked ie., the pointer is not null. What I do in this case is I pass the address of that pointer to the dialog object so it can null it when it is closed - usually preceding the "delete this" statement. The PostNCDestroy method then looks like this :
void CTestDialog::PostNCDestroy()
{
if( m_pSelf )
*m_pSelf = NULL;
delete this;
}
That is the best and easiest way I have come up with to deal with the issue so far.
|
|
|
|
|
in addition to what Aescleal told, over-riding PostNcDestroy is useful when you are dealing with a number of pop up child windows and letting the user to close them dynamically.
|
|
|
|
|
Does it have some functions? to get the file nubmers of the whole computer? How does the vir killer software to do that,how could they control the progress of the whole files of the computer?
I am not a genius, but shed more sweat!
|
|
|
|
|
|
I have what seems to be a random deadlock in my application which I am hoping someone can shed some light on.
The occurance of the deadlock is random but the call stack is far from it... below is the stack I am getting.
0:001> ~0s;kbn
eax=002f0f60 ebx=00000000 ecx=00000f60 edx=00000f60 esi=0079cc10 edi=0015ec54
eip=61088bc4 esp=0015ea90 ebp=0015ebd0 iopl=0 nv up ei pl nz na pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000206
mfc90ud!CWnd::OnWndMsg+0x224:
61088bc4 335508 xor edx,dword ptr [ebp+8] ss:002b:0015ebd8=00000087
# ChildEBP RetAddr Args to Child
00 0015ebd0 61088962 00000087 00000000 00000000 mfc90ud!CWnd::OnWndMsg+0x224
01 0015ebf0 61085d80 00000087 00000000 00000000 mfc90ud!CWnd::WindowProc+0x32
02 0015ec6c 61086346 0015f884 000b1068 00000087 mfc90ud!AfxCallWndProc+0xf0
03 0015ec8c 61081a3b 000b1068 00000087 00000000 mfc90ud!AfxWndProc+0xa6
04 0015ecc8 750c6238 000b1068 00000087 00000000 mfc90ud!AfxWndProcBase+0x5b
05 0015ecf4 750c68ea 610819e0 000b1068 00000087 USER32!InternalCallWinProc+0x23
06 0015ed6c 750ccd1a 00000000 610819e0 000b1068 USER32!UserCallWinProcCheckWow+0x109
07 0015edb0 750ccd81 00c8ba70 00000000 610819e0 USER32!SendMessageWorker+0x581
08 0015edd4 750e0fb1 000b1068 00000087 00000000 USER32!SendMessageW+0x7f
09 0015ee00 750e29a2 00cadd90 00000000 00c87810 USER32!xxxRemoveDefaultButton+0x5f
0a 0015ee30 750dc0cd 00cadd90 00000000 00290b46 USER32!xxxCheckDefPushButton+0x12d
0b 0015ee68 610eebb3 001e0ada 00000000 f53163fb USER32!IsDialogMessageW+0x156
0c 0015ee80 6108f76e 0079cbc8 0058cff8 0015eea8 mfc90ud!CWnd::IsDialogMessageW+0x73
0d 0015ee90 610c730f 0079cbc8 0058cff8 0058cff8 mfc90ud!CWnd::PreTranslateInput+0x6e
0e 0015eea8 6108afbd 0079cbc8 0058cff8 00190712 mfc90ud!CDialog::PreTranslateMessage+0xef
0f 0015eebc 611174df 001e0ada 0079cbc8 0015eedc mfc90ud!CWnd::WalkPreTranslateTree+0x8d
10 0015eed8 61118595 0079cbc8 002f9940 0015eef8 mfc90ud!AfxInternalPreTranslateMessage+0x4f
11 0015eee8 61117555 0079cbc8 002f9940 0015ef18 mfc90ud!CWinThread::PreTranslateMessage+0x25
12 0015eef8 61117391 0079cbc8 0015ef14 61081be9 mfc90ud!AfxPreTranslateMessage+0x25
13 0015ef18 611188ee 002f9940 0015ef30 611173e1 mfc90ud!AfxInternalPumpMessage+0xe1
0:000> .frame c
0c 0015ee80 6108f76e mfc90ud!CWnd::IsDialogMessageW+0x73
0:000> dv
this = 0x0058cff8
lpMsg = 0x0079cbc8
0:000> dt lpMsg -r
Local var @ 0x15ee88 Type tagMSG*
0x0079cbc8
+0x000 hwnd : 0x000a0bb6 HWND__
+0x000 unused : ??
+0x004 message : 0x201
+0x008 wParam : 1
+0x00c lParam : 917536
+0x010 time : 0x32b9eaf
+0x014 pt : tagPOINT
+0x000 x : 2742
+0x004 y : 915
Now the stack from USER32!SendMessageW+0x7f is pretty consistent and it always seems to be message 0x201 (WM_LBUTTONDOWN). Once in this state control is never returned to my code so I am sure I am missing something but I do not know what.
I don't have any code that is looking for WM_LBUTTONDOWN and I have not set anything relating to it, as far as I can tell, and I know when the problem occurs I have not been anywhere near the LBUTTON on my mouse!?!?
In searching around I came across a site in German that says the problem is caused by missing WS_GROUP from the RC. So I added some and I am still having the same problem.
If anyone has had this before and/or can give me some ideas as to what I am missing I would appreciate it.
Many thanks
Alan
|
|
|
|
|
After a little more digging I have discovered that I am getting stuck in a loop inside CWnd with a WM_GETDLGCODE being passed to all of the controls in my application?|?|? The main dialog consists of
BEGIN
CONTROL "",IDC_MNG_TAB,"SysTabControl32",0x0,17,25,248,300
PUSHBUTTON "Edit",IDC_MNG_EDIT,31,345,51,14,WS_GROUP
PUSHBUTTON "Apply",IDC_MNG_APPLY,112,345,50,14,WS_DISABLED | WS_GROUP
DEFPUSHBUTTON "Cancel",IDC_MNG_CANCEL,194,345,50,14,WS_GROUP
CONTROL "",IDC_MAIN_TREE,"SysTreeView32",WS_BORDER | WS_HSCROLL | WS_GROUP | WS_TABSTOP,299,75,209,250
CONTROL "",IDC_RPT_TAB,"SysTabControl32",0x0,544,25,248,300
PUSHBUTTON "Execute",IDC_RPT_EXECUTE,561,345,50,14,WS_GROUP
PUSHBUTTON "Cancel",IDC_RPT_CANCEL,724,345,50,14,WS_GROUP
CONTROL 284,IDC_LOGO,"Static",SS_BITMAP,299,329,209,39
GROUPBOX "Manage",IDC_MNG,7,7,268,369
GROUPBOX "Monitor",IDC_MONITOR,285,7,237,369
GROUPBOX "Report",IDC_RPT,532,7,268,369
GROUPBOX "Status",IDC_ST_STATUS,299,21,209,44
CONTROL 0,IDC_STATUS,"Static",SS_BITMAP,324,31,159,28
END
The group boxes and tab controls are owner drawn.
Any help would be appreciated.
Alan
|
|
|
|
|
H,
I want to read semaphore object names from each active processes. Is there any windows API available? Any method or idea to implement this?
|
|
|
|
|
|
Hi,
I want to fill a vector that memorize multiple instances of a template class (those instances potentially use different template type).
Here my question in code :
template< class T >
class CTest
{
}
CTest< int > a;
CTest< int > b;
CTest< double > c;
vector< CTest< int > * > myints;
myints.push_back( &a );
myints.push_back( &b );
vector< CTest * > all;
all.push_back( &a );
all.push_back( &c );
In short, I don't find the correct way to fill my vector 'all'...
All my tries give a "cannot convert parameter from something to another thing" error.
Anyone know if it is possible and how ?
Thanks in advance for all your answers,
SV
|
|
|
|
|
forwardsim wrote: All my tries give a "cannot convert parameter from something to another thing" error.
Why post an interpretation of the message you see rather than the real message, which would actually help people to figure out what is wrong.
It's time for a new signature.
|
|
|
|
|
Thanks for your interest.
I didn't write the real message for three reasons. First, I try a lot of things and I got a lot of different messages, but all construct from this general sentence. Second, when I copied an example of error, a lot of characters didn't copied correctly. Finally, I was expecting anyway that interesting people will try it.
If you try the example code in my post, the error shown is :
error C2664: 'std::vector<_Ty>::push_back' : cannot convert parameter 1 from 'CTest<t> *__w64 ' to 'CTest *const &'
Hope that helps you figure out what to do...
Thanks again,
SV.
|
|
|
|
|
Quick C++ quiz for you...
If I define a template class:
template<typename T>
class test
{
};
What's the type of a and b in the following declarations?
test<A> a;
test<B> b;
Quick hint - they're not the same.
Now as std::vectors can only hold objects of a single type it's impossible to mix objects of different instantiations of a template class.
Incidentally are you sure you wrote:
std::vector< test * > all;
or something similar? To the best of my knowledge that shouldn't compile and on a bunch of compilers I tried it on they all complained mightily about the fact that test was a template.
Cheers,
Ash
|
|
|
|
|
Thanks.
I understand your point since it's my feeling.
The fact that :
std::vector< test * > all;
passes without complains from my compiler gives me some hopes. Unfortunately, I don't have any other compilator around to try it.
I'm using Microsoft Visual C++ 2005.
SV.
|
|
|
|
|
Ouch, looks like a nasty compiler bug - it should reject the declaration of the vector.
Just had a quick prod with VC++ 2005 - it allows the declaration/definition of the object but you can't do a lot with it, thankfully.
Cheers,
Ash
|
|
|
|
|
Hi,
I tried Microsoft Visual Studio 2010 and
std::vector< test * > all;
doesn't compile.
All my hopes disappeared...
Thanks again...
SV.
|
|
|
|
|
In addition to the post from Ash, you could get to it like this
class base {};
template< class T >
class CTest : public base
{
}
std::vector<base*> all;
and make base the interface to access what you need in the template classes.
|
|
|
|
|
Hi,
It was my first work around test. Unfortunately, it didn't work because I wasn't able to
down-cast from the parent class to the child class. I guess the problem arise only when a member
function has the template class in argument...
Here what happens.
class base
{
};
template< class T >
class CTest : public base
{
public:
T mem;
void add( CTest< T > i )
{
mem += i.mem;
}
template < class S >
void add( CTest< S > i )
{
}
};
std::vector<base*> all;
CTest< int > a;
CTest< double > b;
all.push( (base*) &a );
all.push( (base*) &b );
all[0]->add( all[1] );
I hope my example is clear enough...
SV.
modified on Wednesday, August 18, 2010 5:03 PM
|
|
|
|
|
I probably shouldn't encourage this - heterogeneous collections usually means there's something a bit screwy in your design. But where OO and generic programming collide you can use runtime type information:
class test
{
public:
virtual test &operator+=( const test &other ) = 0;
};
template <typename T>
class T_test : public test
{
public:
T_test( T initial ) : value_( initial )
{
}
virtual test &operator+=( const test &other )
{
if( const T_test<T> *p = dynamic_cast<const T_test<T> *>( &other ) )
{
value_ += p->value_;
}
return *this;
}
private:
T value_;
};
Then you can use it something like:
int main()
try
{
T_test<int> a( 100 );
T_test<double> b( 100.0 );
T_test<int> c( 200 );
test *ptrs[] = { &a, &b, &c };
std::vector<test *> all( ptrs, ptrs + 3 );
T_test<int> result( 0 );
for( std::vector<test *>::const_iterator iter = all.begin(); iter != all.end(); ++iter )
{
result += **iter;
}
}
catch( const std::exception &e )
{
std::cout << e.what() << std::endl;
}
catch( ... )
{
std::cout << "Something went wrong, no idea what!" << std::endl;
}
If this does the sort of thing you're after please consider how to get rid of the dynamic_cast. Oh, and if anyone asks who told you to do this please don't mention my name, tell them it's some other random hacker.
Cheers,
Ash
Edited for tabs and adding the catch(...)
|
|
|
|
|
Hi Ash,
I did think to use a dynamic cast, but I didn't manage to quickly find how to structure things to make it works. Your example is great, simple and fully compatible with my code. I found another solution by restructuring my code, but this solution is not so great even if I don't have to rely on dynamic casting.
I'll think about it tomorrow and choose what seems the best solution. Quickly, I think an approach base on your example will be more interesting, but a little slower because of the dynamic casting. Shouldn't be a problem since this is not a critical part of my code.
Thanks a lot...
Steve.
|
|
|
|
|
Dynamic_cast isn't that slow - it's of the same sort of order as a virtual function dispatch which is about the same order as calling a function in a shared library. The one big bugger with it is that the compiler has problems inlining the operation as it's got no idea what's being thrown at it.
10:1 your code's got far grosser inefficiencies in it than a dynamic_cast. Whenever I profile my apps I'm always surprised at where my code spends it's time. Anyway, good luck!
Cheers,
Ash
|
|
|
|
|
You are running on a complex thing (for C++) generically named as "mumtimethod".
C++ function dispatching works with v-tables only for the one and only implicit parameter of a virtual member function (this ).
If you need to dispatch based on two parameters (that is: when not only the object type but also a function parameter is important) you need to go across two indirections. And since V-tables holds only one you have to workaround.
There are various articles about "multimethods" (try google with that key) with different approaches, but they always have to fall into two indirections, two switches, one swith and one indirection etc.
The complexity of the coding process will be in any case N2 (you have to supply implementation for all the combination) and the execution complexity (whatever you use V-function of switches) will always be "two indrections".
My invite is to don't drop solution only becasue they use virtual function or because they use dynamic_cast: the fact that such implemetations are always slower is a mith: they are slower than direct calls, but where indirections are needed, they are fast exactly like whatever other indirection mechanism. If you define a vector of function pointer to dispatch the calls ... like many of those article, with more or less smart or complex way do, you are implementing in source a v-table!
2 bugs found.
> recompile ...
65534 bugs found.
|
|
|
|
|
Thanks for the information.
I'm going to read about that...
SV.
|
|
|
|
|
Adding some food for thought
#include <vector>
class base
{
public:
template<class T>
static void sum(T &dest, const T &src)
{
dest.privateadd(src);
}
template<class T, class U>
static void sum(T &dest, const U &src)
{
}
private:
template<class T>
void privateadd(const T &t)
{
virtualadd(&t);
}
virtual void virtualadd(const base *arg) = 0;
};
template< class T >
class CTest : public base
{
public:
T mem;
private:
virtual void virtualadd(const base *arg)
{
const CTest<T> *other = static_cast<const CTest<T>*>( arg );
mem += other->mem;
}
};
int main()
{
std::vector<base*> all;
CTest<int> a;
CTest<double> b;
base::sum(a, b); base::sum(a, a); base::sum(a, 1); all.push_back(&a); all.push_back(&b); base::sum(*all[0], *all[1]);
base::sum(*all[0], *all[0]);
}
|
|
|
|
|
Pretty cool!
I was wondering how I could get rid of the dynamic_cast but completely missed the idea of using free functions (or statics) to do it.
Cheers,
Ash
|
|
|
|
|
Still, there must be a better way to attack the problem in the first place. The base class get bloated rather quickly when extending it.
I was a bit annoyed though that I couldn't get back to the a.add(b) syntax. One could of course add that method to the CTest<T> class and use it when you don't have to rely on pointers to the base class. But it would have been nice to always be able to use it.
|
|
|
|
|