The Nightstar Zoo

Nightstar IRC Network - irc.nightstar.net
It is currently Thu Dec 14, 2017 3:16 am

All times are UTC - 6 hours [ DST ]




Post new topic Reply to topic  [ 3 posts ] 
Author Message
PostPosted: Mon Aug 09, 2004 10:37 am 
Offline
Nightstar Graveyard Daemon
User avatar

Joined: Mon Jun 03, 2002 8:30 pm
Posts: 1071
Location: Wouldn't you rather observe my Velocity?
I'm writing some MFC/ATL code that manipulates some dialog elements. I have a "Names" collection (list<CString>) that needs to go into a ComboBox, a Names collection that needs to go into a ListBox, and a Names collection that needs to go into a ListView control.

Disclaimer: we added MFC support to this project by hand after it was created as a Win32 dll. As a result, I can use CStrings and such, but none of my controls are subclassed with MFC controls. So you're not gonna see CString foo; m_ctlCombo.AddString(foo). You're going to see CString foo; SendMessage( hwndCombo, WM_SETTEXT, 0, (LPARAM)(LPCTSTR)foo); etc. Yeah, I know it's gross, but deal. All I'm saying is that's not the part I need refactored. :)

Here is the code for the first one:

Code:
void CCxC3XJobCreate::RefreshNamesCombo( HWND hCtl, const Names& names ) {
   if( ::IsWindow( hCtl ) ) {
      NamesIterConst pName;
      CString strItem;
      TCHAR *pBuf = NULL;
      LRESULT curSel;

      // Get the currently selected item...
      pBuf = strItem.GetBuffer( _MAX_PATH );
      if( pBuf != NULL ) {
         SendMessage( hCtl, WM_GETTEXT, _MAX_PATH, (LPARAM)pBuf );
         strItem.ReleaseBuffer(-1);
      }
      // Clear the combo & re-fill it
      SendMessage( hCtl, CB_RESETCONTENT, 0, 0 );
      for( pName = names.begin(); pName != names.end(); ++pName) {
         SendMessage( hCtl, CB_ADDSTRING, 0, (LPARAM)(LPCTSTR)*pName );
      }
      // Try to restore the previously selected item
      curSel = SendMessage( hCtl, CB_FINDSTRINGEXACT, 0, (LPARAM)(LPCTSTR)strItem );
      if( curSel == CB_ERR ) {
         curSel = 0;
      }
      SendMessage( hCtl, CB_SETCURSEL, curSel, 0 );
   }
}


The code for RefreshNamesListBox is *IDENTICAL* except that the messages it sends are LB_* messages instead of CB_*:

CB_RESETCONTENT -> LB_RESETCONTENT
CB_ADDSTRING -> LB_ADDSTRING
CB_FINDSTRINGEXACT -> LB_FINDSTRINGEXACT
CB_SETCURSEL -> LB_SETCURSEL

I would *LOVE* to refactor this somehow, but even using MFC CComboBox vs. CListBox won't give me the functionality I need, because they don't inherit from a common interface that has ResetContent(), FindStringExact(), and SetCurSel() on it.

The listview code is implemented significantly differently. Finding and restoring the selection is a bit more of a hassle, and really wasn't all that necessary (Refresh is called by a manual intervention of the user, almost always means the listview has completely changed, and the persistence of selection is unimportant when it doesn't, so deselecting an item is okay).

With a ListView, you have to create an LVITEM structure for each element and insert it at a specific position (we use INT_MAX to insert always at the end).

Since the higher-level functionality of ListView restoration is different (no persistence of selection) I'm okay with this function being different. But I'd really like to be able to combine the ListBox and ComboBox methods somehow. And I'd like it to be straightforward enough that the design impact is less severe than just jamming in two nearly identical functions. :P Also, being *able* to combine all three functions would be just spiffy: persistence of selection is not a defect, it's just deemed too hard to pursue right now.

It's a pity that ComboBox doesn't have a GetListBox() method; then the CB method could call the LB method and then fixup its edit control from the restored selection.

Ideas?


Top
 Profile  
 
 Post subject:
PostPosted: Mon Aug 09, 2004 10:42 am 
Offline
Nightstar Graveyard Daemon
User avatar

Joined: Mon Jun 03, 2002 8:30 pm
Posts: 1071
Location: Wouldn't you rather observe my Velocity?
Oooh, here's an evil/interesting solution, at least for combining CB & LB....

Code:
template<typename T>
void CCxC3XJobCreate::RefreshNames( T control, const Names& names ) {
    control.GetText(...);
    control.ResetContent();
    ...etc...
}

...
CListBox lstBox.SubclassWindow( IDC_LISTBOX );
CComboBox cmbBox.SubclassWindow( IDC_COMBOBOX );
...
RefreshNames( lstBox, NamesList );
RefreshNames( cmbBox, NamesList );
...
lstBox.UnsubclassWindow();
cmbBox.UnsubclassWindow();


Top
 Profile  
 
 Post subject:
PostPosted: Mon Aug 09, 2004 4:39 pm 
This is a problem that absolutely BEGS for polymorphism.

Of course, if it were me, I'd note that (at least in the case of CB/LB) the constants are just integers, and create lookup tables. *shug*


Top
  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 3 posts ] 

All times are UTC - 6 hours [ DST ]


Who is online

Users browsing this forum: No registered users and 1 guest


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group