Solved

SubclassWindow()

Posted on 2001-08-06
12
390 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 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
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
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 50 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

Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

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

Introduction: Load and Save to file, Document-View interaction inside the SDI. Continuing from the second article about sudoku.   Open the project in visual studio. From the class view select CSudokuDoc and double click to open the header …
Introduction: Hints for the grid button.  Nested classes, templated collections.  Squash that darned bug! Continuing from the sixth article about sudoku.   Open the project in visual studio. First we will finish with the SUD_SETVALUE messa…
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.
If you're a developer or IT admin, you’re probably tasked with managing multiple websites, servers, applications, and levels of security on a daily basis. While this can be extremely time consuming, it can also be frustrating when systems aren't wor…

719 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