From: Bob Eaton on 26 Nov 2005 00:53 I have some processing I want to do when the OK button of a CPropertySheet/CPropertyPage dialog box is pressed. Unfortunately, (for reasons that aren't clear to me) when the Apply button is pressed, the default handler, OnApply, calls OnOK. This same method(s) are also called when the OK button is pressed!? My first question is, why does it do this? If both methods are called when either button is pressed with no distinction between them, I'm not clear what the benefit of having both is... Second question is, is there any way in OnOK (or OnApply) to tell whether it was called as a result of clicking the OK button versus the Apply button? Thanks, Bob
From: David Wilkinson on 26 Nov 2005 06:27 Bob Eaton wrote: > I have some processing I want to do when the OK button of a > CPropertySheet/CPropertyPage dialog box is pressed. Unfortunately, (for > reasons that aren't clear to me) when the Apply button is pressed, the > default handler, OnApply, calls OnOK. This same method(s) are also called > when the OK button is pressed!? > > My first question is, why does it do this? > If both methods are called when either button is pressed with no distinction > between them, I'm not clear what the benefit of having both is... > > Second question is, is there any way in OnOK (or OnApply) to tell whether it > was called as a result of clicking the OK button versus the Apply button? > > Thanks, > Bob > > Bob: Since CPropertyPage::OnApply and OnOK() are both virtual, you can override them to do whatever you wish. But, personally, the first thing I always do with a property sheet is remove the Apply button. HTH, David Wilkinson
From: Bob Eaton on 26 Nov 2005 19:18 "David Wilkinson" <no-reply(a)effisols.com> wrote in message news:eDJgmyn8FHA.2152(a)TK2MSFTNGP10.phx.gbl... > Since CPropertyPage::OnApply and OnOK() are both virtual, you can override > them to do whatever you wish. But, personally, the first thing I always do > with a property sheet is remove the Apply button. I guess I didn't make myself clear, then: You'd think that OnOK is called when the OK button is clicked and that OnApply is called when the Apply button is called, but this is not the case. The handler for either button is OnApply, which calls OnOK. So that means that *both* methods are ultimately called when either button is clicked. So my question is, when I get OnApply, is there a way to tell whether it was due to the OK button being clicked or the Apply button? And strangely enough, I've overriden them both and they're *not* being called... at least not in the sub-class I need... This much I'm pretty sure is a compiler error (VS.Net 2003). Here's the situation: My application is an ATL/MFC COM DLL. It uses MFC dynamically linked. Prior to building my ATL/MFC COM DLL, I have a smallish shared project which builds a few of the source files into a static library that is also set to "Use MFC in a shared DLL". This static library, then is also linked as part of multiple such ATL/MFC COM DLL projects. My CPropertyPage sub-class, called CAutoConfigPropertyPage, is in the static library as a base class that is also sub-classed in the different COM DLL projects (e.g. CTecAutoConfigPropertyPage). It is in this latter class that I want to override OnApply/OK to detect the click of the OK button. So here's a picture of the situation: MFC DLL virtual BOOL CPropertyPage::OnApply(); Static library: virtual BOOL CAutoConfigPropertyPage::OnApply(); COM DLL: virtual BOOL CTecAutoConfigPropertyPage::OnApply(); When the MFC framework gets the notification that either the OK or Apply button has been pressed, it calls "OnApply", which in the above scenerio *should* call the lowest (i.e. CTecAutoConfigPropertyPage) version. However, it doesn't... Instead, it calls the static library's version (i.e. CAutoConfigPropertyPage). And in fact, that version isn't really needed; initially, I didn't have the CAutoConfigPropertyPage override at all, and when that was the case, it didn't call my override at all, but went directly to CPropertyPage::OnApply). I tried taking the static library out of the situation so that the CAutoConfigPropertyPage source was built directly in the COM DLL project itself, but that didn't help. I've triple checked the declarations in the CTecAutoConfigPropertyPage class and there's nothing wrong with it that would cause the system to think it wasn't an override. So here was my solution: Since the framework was willing to call the first sub-class' implementation (in CAutoConfigPropertyPage in the static library), I now override it there and call a pure virtual function which is implemented in the CTecAutoConfigPropertyPage sub-class. I should mention that it *had* to be a pure virtual function; a simple, non-pure virtual function wouldn't work either!? I've done these things before in other exe projects, so I believe the reason for the bug is the existence of the COM DLL which uses MFC dynamically. I bet if my COM object were implemented in an exe instead, or if it used MFC statically, it would work. But, all this was a side issue: My question still stands: is there a way to tell during OnApply whether it was called as a result of the OK button being called vs. the Apply button (and yes, I need both: there are things I need to do which beg for the Apply button to persist). Bob
From: Jeff Partch [MVP] on 26 Nov 2005 20:32 "Bob Eaton" <pete_dembrowski(a)hotmail.com> wrote in message news:OoDr6gu8FHA.1164(a)TK2MSFTNGP10.phx.gbl... > "David Wilkinson" <no-reply(a)effisols.com> wrote in message > news:eDJgmyn8FHA.2152(a)TK2MSFTNGP10.phx.gbl... > So my question is, when I get OnApply, is there a way to tell whether it was > due to the OK button being clicked or the Apply button? Does GetCurrentMessage return valid info in this context? -- Jeff Partch [VC++ MVP]
From: David Wilkinson on 27 Nov 2005 07:25 Bob Eaton wrote: > "David Wilkinson" <no-reply(a)effisols.com> wrote in message > news:eDJgmyn8FHA.2152(a)TK2MSFTNGP10.phx.gbl... > >>Since CPropertyPage::OnApply and OnOK() are both virtual, you can override >>them to do whatever you wish. But, personally, the first thing I always do >>with a property sheet is remove the Apply button. > > > I guess I didn't make myself clear, then: You'd think that OnOK is called > when the OK button is clicked and that OnApply is called when the Apply > button is called, but this is not the case. The handler for either button is > OnApply, which calls OnOK. So that means that *both* methods are ultimately > called when either button is clicked. > > So my question is, when I get OnApply, is there a way to tell whether it was > due to the OK button being clicked or the Apply button? > [snip] > > But, all this was a side issue: My question still stands: is there a way to > tell during OnApply whether it was called as a result of the OK button being > called vs. the Apply button (and yes, I need both: there are things I need > to do which beg for the Apply button to persist). > Bob: I'm not sure about your virtual function issue, but you're right, I did misunderstand your original question, because I did think the naive expectation about the relationship between the buttons and the handlers was the reality. It is this kind of thing that led me long ago to always remove the Apply button. It also does not really make sense to me from a user perspective, and I remember being confused by it when I first moved to Windows from Mac. So have you considered doing this? Otherwise, perhaps you have to catch the button clicks in the Property Sheet. Then you really CAN do what you want. I actually use a modified CPropertyPage base class in which I have virtual BOOL OnOK(); virtual BOOL OnCancel(); virtual BOOL OnApply(); virtual BOOL OnHelp(); The base class versions of these functions returns TRUE; BOOL CMyPropertySheet::OnCommand(WPARAM wParam, LPARAM lParam) { WORD code=HIWORD(wParam); WORD nID=LOWORD(wParam); if(code == BN_CLICKED) { switch (nID) { case IDOK: if (!OnOK()) { return 1; } break; case IDCANCEL: if(!OnCancel()) { return 1; } break; case ID_APPLY_NOW: if(!OnApply()) { return 1; } break; case IDHELP: if(!OnHelp()) { return 1; } break; } } return CPropertySheet::OnCommand(wParam, lParam); } Now in my actual derived class I can do anything I like. HTH, David Wilkinson
|
Next
|
Last
Pages: 1 2 Prev: Transparent Checkbox : How to Next: CListCtrl Setting the Focus to a Row through Code |