15 мая 2023 года "Исходники.РУ" отмечают своё 23-летие!
Поздравляем всех причастных и неравнодушных с этим событием!
И огромное спасибо всем, кто был и остаётся с нами все эти годы!

Главная Форум Журнал Wiki DRKB Discuz!ML Помощь проекту


Class Wizard reorders methods and props

Fredrik Gunne -- fgunne@agema.se
Thursday, January 23, 1997

Environment: VC++ 4.1, NT 4.0

When properties and methods are added to an OCX using the class wizard,
they are not added to the end of the list of properties and methods.
Instead, they are inserted into the list, changing the relations between
the OCX's methods and their dispIDs.
How do you get around this?

More info:
Consider an OCX with one method and one property, with this .ODL file:
...
		properties:
			// NOTE - ClassWizard will maintain property information here.
			//    Use extreme caution when editing this section.
			//{{AFX_ODL_PROP(COrderCtrl)
			[id(1)] short Property1;
			//}}AFX_ODL_PROP

		methods:
			// NOTE - ClassWizard will maintain method information here.
			//    Use extreme caution when editing this section.
			//{{AFX_ODL_METHOD(COrderCtrl)
			[id(2)] void Method1();
			//}}AFX_ODL_METHOD
...
An application using this OCX would call IDispatch::Invoke with dispidMember = 2 to invoke Method1

Know, suppose someone adds one property and one method to the OCX, using the class wizard, giving
this ODL-file:
		properties:
			// NOTE - ClassWizard will maintain property information here.
			//    Use extreme caution when editing this section.
			//{{AFX_ODL_PROP(COrderCtrl)
			[id(1)] short Property1;
			[id(2)] short property2;    <****** dispid 2 now points to property2!
			//}}AFX_ODL_PROP

		methods:
			// NOTE - ClassWizard will maintain method information here.
			//    Use extreme caution when editing this section.
			//{{AFX_ODL_METHOD(COrderCtrl)
			[id(3)] void Method1(); <******* Method1 has dispid 3!
			[id(4)] void Method2();
			//}}AFX_ODL_METHOD

Obviously, since the class wizard has changed the order of the properties and methods, 
Method1 no longer is represented by dispid 2, but dispid 3. In other words, all applications
that use the OCX must be recompiled with the new TLB file in order to update its dispids.
This is very unfortunate, since this means it's not possible to easily update the OCX with new and
improved versions.

Is there anyway to make the class wizard retain the order of the dispids, adding the props and methods
to the end of the list of dispids. If not, are there any other workarounds? If you have to change the ODL 
by hand, what else has to be changed?

Regards
Fredrik







David Razzetti -- raz@jump-jet.demon.co.uk
Friday, January 24, 1997

[Mini-digest: 2 responses]

Hi Fredrik

=46irstly your question concerning the mapping of IDs to methods and
functions.  This problem occurs for automation servers as well
(suprise, suprise).  From an automation server point of view, its my
understanding that the preferred method to overcome this is to have
each client dynamically map the function names to the IDs at run time,
via calls to the OLE typelibrary support APIs.  This allows the server
to be modified without affecting its clients, as long as the
modifications don't result in the removal of methods/properties.

At least one other compiler vendor's OLE code does indeed do this (the
vendor has to remain nameless - this is a Microsoft list after all
:-).  However, if you look at the stubs produced by ClassWizard, you
will see that the mapping has been fixed and the IDs are hard coded.
I would be interested to hear from anyone as to why this has been done
this way (appart from the obvious speed of execution benefit from not
having to do the lookup!)

Solutions :-
I know of no method to force ClassWizard to use the same IDs even
after new properties/methods are added.  You can however use the
macros that allow you to explicitly specify the ID to be used.

Eg replace a line such as
	DISP_PROPERTY_NOTIFY(CCircCtrl, "CircleShape", m_circleShape,
OnCircleShapeChanged, VT_BOOL)
in your source code's dispatch map with
	DISP_PROPERTY_NOTIFY_ID(CCircCtrl, "CircleShape", 4,
m_circleShape, OnCircleShapeChanged, VT_BOOL)
so that the ID is always 4.

You have to take a LOT of care with this since you are responsible for
maintaining the tie-up between the value declared in the source file
and the value in the ODL.  You may also have to take care that you
don't annoy (break) class wizard - perhaps by moving the altered lines
in the source code outsize of the class wizard {{ and }} symbols and
similarly for the ODL entries.

Note also that the macros ending in _ID don't appear to be documented
anywhere.  They may not be a Microsoft published interface and so may
change/disappear in future releases.  I leave it up to you to check
these things out.

I personally think that the _ID macros are essential to MFC's OLE
implimentation, since they appear to be the only way to take complete
control over the dispatch ID used for a property or method.
Take for example an automation server containing a collection of
objects.  According to Brockschmidt's book on OLE (page 664), a
container should offer a method named _NewEnum to expose an object
supporting the IEnumVARIANT interface to allow the client to enumerate
the objects in the container.  The dispach ID of this method has to be
set to the constant DISPID_NEWENUM.  The only way that I can see of
doing this with MFC is to use the _ID macros !

You may also be interested to know that the last time I was developing
automation servers (on VC 4.0) the class wizard would not accept an
OLE method starting with an underscore!  In order to provide a
_NewEnum method, I had to edit by hand the code produced by wiz to add
the underscore character.  Such is (or was) life !

Hope this helps.

Dave Razzetti
raz@jump-jet.demon.co.uk

On Thu, 23 Jan 1997 08:59:00 +0100, you wrote:

>Environment: VC++ 4.1, NT 4.0
>
>When properties and methods are added to an OCX using the class wizard,
>they are not added to the end of the list of properties and methods.
>Instead, they are inserted into the list, changing the relations between
>the OCX's methods and their dispIDs.
>How do you get around this?
>
>More info:
>Consider an OCX with one method and one property, with this .ODL file:
>...
>		properties:
>			// NOTE - ClassWizard will maintain property information here.
>			//    Use extreme caution when editing this section.
>			//{{AFX_ODL_PROP(COrderCtrl)
>			[id(1)] short Property1;
>			//}}AFX_ODL_PROP
>
>		methods:
>			// NOTE - ClassWizard will maintain method information here.
>			//    Use extreme caution when editing this section.
>			//{{AFX_ODL_METHOD(COrderCtrl)
>			[id(2)] void Method1();
>			//}}AFX_ODL_METHOD
>...
>An application using this OCX would call IDispatch::Invoke with =
dispidMember =3D 2 to invoke Method1
>
>Know, suppose someone adds one property and one method to the OCX, using=
 the class wizard, giving
>this ODL-file:
>		properties:
>			// NOTE - ClassWizard will maintain property information here.
>			//    Use extreme caution when editing this section.
>			//{{AFX_ODL_PROP(COrderCtrl)
>			[id(1)] short Property1;
>			[id(2)] short property2;    <****** dispid 2 now points to property2!
>			//}}AFX_ODL_PROP
>
>		methods:
>			// NOTE - ClassWizard will maintain method information here.
>			//    Use extreme caution when editing this section.
>			//{{AFX_ODL_METHOD(COrderCtrl)
>			[id(3)] void Method1(); <******* Method1 has dispid 3!
>			[id(4)] void Method2();
>			//}}AFX_ODL_METHOD
>
>Obviously, since the class wizard has changed the order of the =
properties and methods,=20
>Method1 no longer is represented by dispid 2, but dispid 3. In other =
words, all applications
>that use the OCX must be recompiled with the new TLB file in order to =
update its dispids.
>This is very unfortunate, since this means it's not possible to easily =
update the OCX with new and
>improved versions.
>
>Is there anyway to make the class wizard retain the order of the =
dispids, adding the props and methods
>to the end of the list of dispids. If not, are there any other =
workarounds? If you have to change the ODL=20
>by hand, what else has to be changed?
>
>Regards
>Fredrik
>
>
>
>

-----From: "P.J.  Tezza" 

Dear Fredrik,

We had a similar problem with our application's OLE Automation server 
objects. For performance, our application's macro language is compiled into 
an intermediate form. The intermediate form's data structures store DISPIDs 
instead of strings. We also have some sample Visual C++ OLE Automation 
controller applications which use hardwired DISPIDs.

To make sure our OLE Automation server object member DISPIDs did not change 
(and that they were logically numbered), we moved our property and method 
declarations out from under ClassWizard's control by moving them outside 
the AFX_DISPATCH(...) and AFX_DISPATCH_MAP(...) comments. We then converted 
to using the DISP_PROPERTY_EX_ID(...),  DISP_FUNCTION_ID(...), and 
DISP_DEFVALUE_ID() macros so we could specify the DISPIDs explicitly. Due 
to a MFC 2.5 implementation "feature", ID values had to be greater than the 
number of object members (see OLEDISP1.CPP(GetDispEntry(MEMBERID memid))). 
This may not be a problem with MFC 4.x.

You really don't lose too much by moving the member declarations outside 
the ClassWizard comments - you can no longer delete them with ClassWizard. 
It is possible that much of this has changed for MFC 4.x, but I doubt it - 
the application was rebuilt with MFC 4.x about a year ago and is working 
fine.

PJ

----------
From: 	Fredrik Gunne[SMTP:fgunne@agema.se]
Sent: 	Thursday, January 23, 1997 2:59 AM
To: 	mfc-l@netcom.com
Subject: 	Class Wizard reorders methods and props

Environment: VC++ 4.1, NT 4.0

When properties and methods are added to an OCX using the class wizard,
they are not added to the end of the list of properties and methods.
Instead, they are inserted into the list, changing the relations between
the OCX's methods and their dispIDs.
How do you get around this?

More info:
Consider an OCX with one method and one property, with this .ODL file:
..
		properties:
			// NOTE - ClassWizard will maintain property information here.
			//    Use extreme caution when editing this section.
			//{{AFX_ODL_PROP(COrderCtrl)
			[id(1)] short Property1;
			//}}AFX_ODL_PROP

		methods:
			// NOTE - ClassWizard will maintain method information here.
			//    Use extreme caution when editing this section.
			//{{AFX_ODL_METHOD(COrderCtrl)
			[id(2)] void Method1();
			//}}AFX_ODL_METHOD
..
An application using this OCX would call IDispatch::Invoke with 
dispidMember = 2 to invoke Method1

Know, suppose someone adds one property and one method to the OCX, using 
the class wizard, giving
this ODL-file:
		properties:
			// NOTE - ClassWizard will maintain property information here.
			//    Use extreme caution when editing this section.
			//{{AFX_ODL_PROP(COrderCtrl)
			[id(1)] short Property1;
			[id(2)] short property2;    <****** dispid 2 now points to property2!
			//}}AFX_ODL_PROP

		methods:
			// NOTE - ClassWizard will maintain method information here.
			//    Use extreme caution when editing this section.
			//{{AFX_ODL_METHOD(COrderCtrl)
			[id(3)] void Method1(); <******* Method1 has dispid 3!
			[id(4)] void Method2();
			//}}AFX_ODL_METHOD

Obviously, since the class wizard has changed the order of the properties 
and methods,
Method1 no longer is represented by dispid 2, but dispid 3. In other words, 
all applications
that use the OCX must be recompiled with the new TLB file in order to 
update its dispids.
This is very unfortunate, since this means it's not possible to easily 
update the OCX with new and
improved versions.

Is there anyway to make the class wizard retain the order of the dispids, 
adding the props and methods
to the end of the list of dispids. If not, are there any other workarounds? 
If you have to change the ODL
by hand, what else has to be changed?

Regards
Fredrik





begin 600 WINMAIL.DAT
M>)\^(A 6`0:0" `$```````!``$``0>0!@`(````Y 0```````#H``$(@ <`
M& ```$E032Y-:6-R;W-O9G0@36%I;"Y.;W1E`#$(`0V ! `"`````@`"``$$
MD 8`# $```$````,`````P``, (````+``\.``````(!_P\!````/P``````
M``"!*Q^DOJ,0&9UN`-T!#U0"`````&UF8RUL0&YE=&-O;2YC;VT`4TU44 !M
M9F,M;$!N971C;VTN8V]M```>``(P`0````4```!33510`````!X``S !````
M$0```&UF8RUL0&YE=&-O;2YC;VT``````P`5# $````#`/X/!@```!X``3 !
M````$P```"=M9F,M;$!N971C;VTN8V]M)P```@$+, $````6````4TU44#I-
M1D,M3$!.151#3TTN0T]-`````P``.0`````+`$ Z`0````(!]@\!````! ``
M``````(]+ $$@ $`+ ```%)%.B!#;&%S`' `
M`0```"P```!213H@0VQAL"@P!0$P-4`@!C: K P*J]M)#'&9"/@(=%T1&9 %L"%P
M1$E34#Q)1 0@"X 9D2&A;V:[+:(+@&!: ", -@%] ED2.)!"#L=V@CP",@=1'P(8$+
M(-<#\!K1+K8N((Q4*, `P/YK,3$N$2=3)&\E>2AP&;">8B61+L8K("&P;F\%
M0/<1L1W0(7 H`' AL",0(^!Y/-%E>2+@!) A".B(P`^0"8P#D0*4$IR(=!-1D,@>#(N-2E@,<)(\CET(C9F'\ N`B(G0"\`
M(':_!T *4 0@(9(J43K@( G!_RM!!< \X0.@1<(^="^R.DL]!" H$? A<#CA
M+L(Q+E1#4$A01Q(`1 0`< )%,]%Y*$U%34+O2^!5P3JQ.[ I7' KPBEQ?P# 
M/E$[\5;1(= B>U.B--0N>#;M60A@(%<1/C+^9"01!4 :8#6A.4 WX2W@?R,@
M1%LZID$^17="^4BW(/@M('E@(2/0`Z [X#W!_SQ18S(BL"M11/,B\T+Y)C#V
M205 *7%P4" `D"*A/-3_8;,OP2,0*7$1P"F!/#,AL%1_"*3 J8BH1
M-1$%L"IK1+)F"X!E-NU02D<@C KT([ Q.# "T6GP+3$T- WP#-!UPPM9WC$8
M@")Q&: Z@2UWYPJ'WW:;##!W9B ``W Z>.YW9C,,@A_V($="D'*P6U-@3510
M.F8I$'U!0.LI,0# +A'P77B/>9T&8%\",'K/>]LKX AP;TG0$H`<"D@
M6V!3T#,G0! Q.3DW4] Z-3E]$W!-?M]YG3?0@1][VVU1$: M;$!RL'0IH2[_
M*:&%'W_N;7 EXH<_>]M"\_\A4&5$&M %L 2!*&% TP0@FSRB/_)S<^]T\S,V
M=F>_%;(,`7=F6S!$H -@;DCR+8R 5C*"7O Q)T!.5/]>X0IV(/9)HC_U")"0
M)(_''RZ1(: -L$IC`Y%/0UC_2JE!4001`_!#8B!V/3.80O\[XIB'1<()\"^C
M1<(CL!F0[R^REM^/XS;F22]4)T";9_\O04HD*C.==B= /"-*UAK0]PM@--0Z
MX'0]@ GPFOB9,G\H4H_9/3$V(#N141 VN4C^;P?@8,!F0RE <-$#8$*1=6L#
M/R",32Z""X "$#K_"H4(4 "!0K*9%2+TXP54UH5)0+! \ `@<[! !>PQ.[\OO/9]PX"]JI#=_[#'C\6Q_[,/M!^U)D#%MC__
MQH^X7[EONG^[C[R?O:9;D+Q42*\@OF_0G\"",L#1U'9O.[%-0-,Q3[#!__?#
M#])7K[Y!`Z!N2DJV*7%_K!-0PSX25;%;`2/@$; Z_CJ@$-6 ."$B\Z;".[#5
MT/TZTSU3T$IR"X#=<]75((SZ2SO@=R= ,C CD&$R,5+_K**8@4'AK:FM1T#%
MG)690>\G0)F/FI16\&E$HIKWVX+]KS MKVJPO['/QU_(;[3__[8/RW_,C\V?
MSJ_/O];_O7]_TP_4'\"OP;_4;_DE/_8R\COP\CPJ_6/>!=[QX2'?::$J,00@
M*E'\=R'Z/]>/_\0OQ3_&3^L/[!_)?^Y?] __\'_QC_*?\Z_TO]'_]K_ZK_WX
MT#/57_T`_57]L-75:U.M_=4S_]_X6#03/#+63V<`S]AOX)9/8D2@<+!S_SY 
MX5$>P"<@Y9]K6T7"CU/_G3:>/X_C)T"IUA4%9M@I"K85\M[DG^\0DR1Q%Y;P!1<6&1_F'?D1VO?+ 'LQ]_+;5.
M4?^8D$K6D(.7>IKVG*^=MBVV?U6PG5 QH4Y1F%$W9R98:_^HI*E 0")F4FM@
M2A!* \2@^1?Y*$5C.2_(H5?8H0`$Z0``,`$! ``````P`1$ ````! ```#T``0````4```!213H@``````,`#33]-P``
"L D*
`
end





| Вернуться в корень Архива |