Go Premium for a chance to win a PS4. Enter to Win

x
?
Solved

SubclassWindow()

Posted on 2001-08-06
12
Medium Priority
?
419 Views
Last Modified: 2013-11-20
I have implemented a property sheet with 8 pages. In each of my propery pages I have lot of controls including edit controls, radio buttons, check boxes etc. I was thinking of a good way to handle these controls. Like, if I use the DDX/DDV for each control its virtually impossible. I heard about using SubclassWindow() for attaining this. But I didn't get it much. I am sure someone out there have done this. It would be appreciated if someone could explain this with a sample code for the same. Waiting for an early response..
0
Comment
Question by:prasanthpooyath
  • 5
  • 4
  • 2
  • +1
12 Comments
 
LVL 1

Expert Comment

by:kkarunakar
ID: 6358420
Hi there!!
I guess you can use GetDlgItem() in more proper way to get the handle of one control. If you don't want to do DDX/DDV.
Like.Suppose you want the control on page 5 .
CPage5 *pPage5 = (Get your page file pointer using parent class. may be like
GetParent()->GetPage5().)
After getting page5 (that i guess it will derived of some dialog..or may be one window control.
You can access GetDlgItem(IDC_CONTROL1) .
Ex:
CButton *pButton = pPage5->GetDlgItem(IDC_AXXX);
ASSERT(pButton!= NULL);

I guess it will help you .
Thanks
Keshav
0
 
LVL 49

Expert Comment

by:DanRollins
ID: 6358607
Use the ClassWizard to create a variable for each item.  Let MFC doo the work for you!

Now in the case of a CPropertySheet, I have found this technique to work best...

Derive a class from CPropertySheet.  Make members for each of the CPropertySheets.  Before calling DoModal, set all the vars:

CMySheet cSheet;
//---------------------- set vars for Pg 1
cPg1.nFoo= 1;
cPg1.sBlech= "hi there!";

//---------------------- set vars for Pg 2
cPg2.nBar= 7777;
cPg2.sNameLast= "Jones";

int nRet= cSheet.DoModal();
if ( nRet== IDOK ) {
   //----------------------- save vares from pg 1
   gnMySavedVar= cPg1.nFoo;
   ... etc...
   //----------------------- save vares from pg 1
   gsSavedLastName= cPg2.sNameLast;
}

-- Dan

0
 

Author Comment

by:prasanthpooyath
ID: 6358626
Thanx for the info. But I think I know that... This is fine with less controls in the pages. But in my case I am having atleast 150 CEdit controls in a single PropertyPage to be handled.  Just imagine how it would look to have 150 variables for each edit controls/...  So I think there is some other method other than the ClassWizard one by which u code it yoiurselves. I just know that u use SubclassWindow() for that. But don't know anything else. Please give an example code to help me out from this...
0
VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

 
LVL 4

Expert Comment

by:albay
ID: 6358834
hi.

you can use ON_CONTROL_RANGE event handler...

define this in your .cpp file

BEGIN_MESSAGE_MAP(CDenemeDlg, CDialog)
     //{{AFX_MSG_MAP(CDenemeDlg)
     ON_WM_SYSCOMMAND()
     ON_WM_PAINT()
     ON_WM_QUERYDRAGICON()
     //}}AFX_MSG_MAP
     ON_CONTROL_RANGE(EN_CHANGE, IDC_EDIT1, IDC_EDIT150, OnChangeEdit)  //you use 150 edit-boxes only define this
END_MESSAGE_MAP()

pay attention to use handler outside //}} AFX_MSG_MAP

and define this in .h file
        //{{AFX_MSG(CDenemeDlg)
     virtual BOOL OnInitDialog();
     afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
     afx_msg void OnPaint();
     afx_msg HCURSOR OnQueryDragIcon();
     //}}AFX_MSG
     afx_msg void OnChangeEdit(UINT nID); //only define this
     DECLARE_MESSAGE_MAP()


and OnChangeEdit:::

void CDenemeDlg::OnChangeEdit(UINT nID)
{
     UINT index=nID - IDC_EDIT1;
     switch(index)
     {
     case 0:
     case 1:
     case 2:
          ...
          ...
     case 149:
     }
}

hope this helps
0
 
LVL 4

Expert Comment

by:albay
ID: 6358874
by using above code, you can trap the OnChangeEdit handler on which edit-box is changed.

best regards,
albay
0
 

Author Comment

by:prasanthpooyath
ID: 6358888
Thanx for the info. But again I was looking for a one-to-one  substitute for DDX/DDV for my 150 Edit Controls.
0
 
LVL 49

Expert Comment

by:DanRollins
ID: 6360673
>>in my case I am having atleast 150 CEdit controls in a single PropertyPage

You should seriously consider a redesign.  That is way too much information to present in one dialog box.

Nevertheless, I will solve your problem for you, even though you offer only 50 pts.

You need to arrange your code so that rather than having 150 CString member variables, you have a single CStringArray.  Then you manually modify your RC file so that the EDIT controls have sequentially-numbered ID.  For instance, the first one is 1000, the second is 1001, etc.

Replace all of the individualy DDX transfers with a loop like so:

void CMyPg::DoDataExchange(CDataExchange* pDX)
{
   CPropertyPage::DoDataExchange(pDX);
   //{{AFX_DATA_MAP(CMyPg)
   //}}AFX_DATA_MAP

    for (int j=0; j<150; j++ ) { // 150= number of controls
          DDX_Text(pDX, 1000+j, m_asEdits[j] );
    }
}

Before calling DoModal(), fill the CStringArray with values from aa file or whatever.  Afterward, the data entered by the user will be in the CStringArray strings.

This will solve your problem.

-- Dan
0
 

Author Comment

by:prasanthpooyath
ID: 6370573
Thanx a lot friends for all your valuable suggestions. But I found the following method as a li'l more managable in my case. Thanx to Zoppo.

// sample for four edit controls

// in header
const int iEditNum = 4;
const int iEditCtrl[iEditNum] = {
          IDC_EDIT1,
          IDC_EDIT2,
          IDC_EDIT3,
          IDC_EDIT4,
};

class CDtDlg : public CDialog
{
   ...
   public:
   // Dialog Data
   //{{AFX_DATA(CDtDlg)
   enum { IDD = IDD_DT_DIALOG };
   //}}AFX_DATA
   CString     m_szEdit[iEditNum]; // make sure this is outside of AFX_DATA block
   ...
}

// in .cpp file
CDtDlg::CDtDlg(CWnd* pParent /*=NULL*/)
    : CDialog(CDtDlg::IDD, pParent)
{
   //{{AFX_DATA_INIT(CDtDlg)
   //}}AFX_DATA_INIT
   for ( int i = 0; i < iEditNum; i++ ){
      m_szEdit[i] = _T("");
   }
...
}

void CDtDlg::DoDataExchange(CDataExchange* pDX)
{
   CDialog::DoDataExchange(pDX);
   //{{AFX_DATA_MAP(CDtDlg)
   //}}AFX_DATA_MAP
   for ( int i = 0; i < iEditNum; i++ ){
      DDX_Text(pDX, iEditCtrl[i], m_szEdit[i]);
   }
}
0
 
LVL 49

Expert Comment

by:DanRollins
ID: 6375332
That is not ZOPPOs answer, it is mine!

The core of it is the manually-added DDX_Text loop in the AFX_DATA_MAP.  Why don't you give credit where credit is due?  Do you expect people to help you in the future?

-- Dan


0
 
LVL 49

Expert Comment

by:DanRollins
ID: 6420421
hi prasanthpooyath,

Do you have any additional questions?  DO any comments need clarification?

-- Dan
0
 
LVL 49

Accepted Solution

by:
DanRollins earned 150 total points
ID: 6443875
hi prasanthpooyath,

Do you have any additional questions?  DO any comments need clarification?

-- Dan
0
 

Author Comment

by:prasanthpooyath
ID: 6443908
Thanx for your kind help..and sorry for keeping u wait ....
0

Featured Post

Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Introduction: Displaying information on the statusbar.   Continuing from the third article about sudoku.   Open the project in visual studio. Status bar – let’s display the timestamp there.  We need to get the timestamp from the document s…
Introduction: The undo support, implementing a stack. Continuing from the eigth article about sudoku.   We need a mechanism to keep track of the digits entered so as to implement an undo mechanism.  This should be a ‘Last In First Out’ collec…
This Micro Tutorial will teach you how to add a cinematic look to any film or video out there. There are very few simple steps that you will follow to do so. This will be demonstrated using Adobe Premiere Pro CS6.
This video will show you how to get GIT to work in Eclipse.   It will walk you through how to install the EGit plugin in eclipse and how to checkout an existing repository.

972 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question