SetActivePage doesn't work
Maurits Rijk 7 84941 -- rijkm@ehv.tass.philips.com Friday, January 12, 1996 Hi Folks, Does anybody know why the function SetActivePage on a PropertySheet does not work? I defined a PropertySheet with 5 pages (4 on row1 and 1 on row2). I call the function SetActivePage(i), with i being a value between 0-4, but nothing seems to happen. At least no page change occurs. What happens, is that after a few tries, the page contents are not correct. But it can be corrected by selecting a few tabs on the PropertySheet. I'm using MSVC version 1.52c. Thanks, Maurits Rijk
Rick Esterling -- rick@eco.twg.com Monday, January 15, 1996 On 12 Jan 96 at 14:57, Maurits Rijk (7 wrote: > Does anybody know why the function SetActivePage on a PropertySheet > does not work? If you look in DLGPROP.CPP, you'll see that whenever MFC calls this member method, it also makes some other calls to actually get the page active, in the proper Z-Order, etc. To the best of my knowledge, SetActivePage() was not a documented call until MFC 4.0, so trying to use that function with an earlier version of MFC can obviously cause unpredicatable results. There is, however, another undocumented method you can use that does work for the version of MFC you're using: CYourDerivedPropSheet::SomeMemberMethod() { m_tabRow->SetCurSel( nPage ); } m_tabRow is a protected member so you'll have to use it from a CPropertySheet-derived class, not just a CPropertySheet-derived object. Give that a try and I think you'll be good to go. > I'm using MSVC version 1.52c. Thanks for including this info. Makes is easier to offer assistance. Good luck, Rick ------------------------------------------------------------- Rick Esterling The Wollongong Group, Inc. Senior Software Engineer McLean, VA http://widget.eco.twg.com:1080 http://www.twg.com
David Goldfarb -- deg@degel.com Wednesday, January 17, 1996 Date: Mon, 15 Jan 1996 12:18:06 -0005 From: Rick EsterlingSubject: Re: SetActivePage doesn't work ... m_tabRow is a protected member so you'll have to use it from a CPropertySheet-derived class, not just a CPropertySheet-derived object. Give that a try and I think you'll be good to go. There is actually a way, condoned by C++, to access protected members from anywhere. The following is gross, so stop reading here if you have a weak stomach! Basically, C++ has a designed-in security hole, at least compared to some other OO languages (I'm personally a CommonLisp/Flavors/CLOS bigot, and my biases may be showing here). The protected/private style protection applies to the entire class, and not to individual objects. Therefore, an object of any type that is based on CWnd is able to access protected CWnd members of any other object that is a CWnd or of a class based on CWnd. This technique, though evil, is occasionally incredibly useful when working with MFC, which relies a bit too heavily on protected members (and way too heavily on non-virtual functions, but that's a subject for another thread). In any event, I've enclosed a code fragment below that does this. The actual problem that I was solving there is irrelevant; it was a subtle problem with our use of CTL3D in a particular application. The technique, though, is generally applicable whenever you need to access a protected member of CWnd and can't use cleaner mechanisms. Notes: - I still don't understand why the downward cast is needed in GetHisSuperWndProcAddr. Any C++ language lawyers care to enlighten me? (Or is this just a Microsoft bug?) - Looking at this code now, it seems pretty clear to me that GetHisSuperWndProcAddr should be defined as a static method, thus obviating the need to create the global oBarfoliousSnarfer. Not tested, so I'm leaving the code as is here. - Sorry, I will not explain the silly names used below to this whole forum. Anyway, here's the code. // This class, with it euphonious name, exists to enable us to access a // protected member of CWnd, the function, GetSuperWndProcAddr, from // outside of CWnd-derived class. This is needed by the function // Ctl3dSubclassCtlForMFC below. // We are relying on the fact that C++ protection works at the class // level, rather than the object level -- a member function is able to // access the private data of any object of it's class, and not just of // the object pointed to by the "this" pointer. Similarly, it is able // to access proteced data of ancestor classes for any object of its // type, not just the "this". // We take advantage of this fact to write a public accessor that can // retrieve the ostensibly protected data guarded by the function // CWnd::GetSuperWndProc. // Actually, GetSuperWndProc is a virtual function and what we are // going to get is the appropriate function for the runtime type of // pWnd, but that all just works in the usual way, since the virtual // function mechanism happens at runtime and is completely unrelated to // the compile-time public/protected/private mechanism. class CWoundedHorseBarfoSnarfoWnd : CWnd { public: WNDPROC *GetHisSuperWndProcAddr(CWnd *pWnd) { // It is not at all clear to me why the downward pointer cast is // needed in the next line. It seems it should be equally // permissible to access the protected state of a CWnd. But, this // works only with the cast. return ((CWoundedHorseBarfoSnarfoWnd *)pWnd)->GetSuperWndProcAddr(); } }; // This is just a global object used to trampoline into GetSuperWndProcAddr. static CWoundedHorseBarfoSnarfoWnd oBarfoliousSnarfer; // ... [Many lines of comment elided here] // To get around the problem, we've defined the following function that // splices the CTL3D subclassing into the proper place in the chain. // This has to be a global function, rather than a member of some // CWnd-derived class, since we have to support controls of classes // that are defined by MFC, as well as those of our own classes. // Technically, we could make this be a method of CWnd, but we don't // want to modify the MFC sources. Furthermore, because we have to use // a protected member of CWnd, we have to use the BarfoSnarfo hack // described above. VOID Ctl3dSubclassCtlForMFC(CWnd *pWnd) { // Get the old super procedure. WNDPROC *lplpfn = oBarfoliousSnarfer.GetHisSuperWndProcAddr(pWnd); ... } David =================================================== David Goldfarb Editor, The GUI Bits Degel Software Tools Ltd. Email: deg@degel.com 7 Ha'Iris St. Tel: +972 (2) 991-7033 Beit Shemesh, Israel Fax: +972 (2) 991-6718 (Ask about our new "advisory consulting" service) ===================================================
| Вернуться в корень Архива |