CCheckListBox is giving me trouble!
Hulemannen -- elg2@nobipol.unit.no Friday, August 02, 1996 Environment: VC++ 4.0,NT 3.51 Here's my problem: - a dialog created with the dialog editor that also contains a list box - with class wizard I derived a memeber variable - CListBox m_dlListBox - in the class CMyDialog. I then changed it to a CCheckListBox-class. - in OnCreate I added this code: CRect rect; m_dlgListBox.GetItemRect(IDC_LIST, &rect); int nRet = m_dlgListBox.Create(WS_CHILD | WS_VISIBLE | LBS_STANDARD | LBS_HASSTRINGS | LBS_OWNERDRAWFIXED | LBS_OWNERDRAWVARIABLE , rect, this, IDC_LIST); ASSERT(nRet != 0); "GetItemRect(IDC_LIST, &rect);" causes the following ASSERT failure in line 643 in AFXWIN2.INL: _AFXWIN_INLINE int CListBox::GetItemRect(int nIndex, LPRECT lpRect) const { ASSERT(::IsWindow(m_hWnd)); return (int)::SendMessage(m_hWnd, LB_GETITEMRECT, nIndex, (LPARAM)lpRect); } I have discovered that this function can only be used after Create is called, but I need the parameter 'rect' it passes to run Create correctly. I can replace the second paramater 'rect' in Create with CRect(0,0, 200,200) for example and then I can see the list, although it isn't placed correctly in the dialog and seems to be hiding behind text,buttons etc. Passing NULL instead of 'rect' produces an error and trying to read the listbox-position and size from the dialog editor and passing these doesn't produce produce satisfactory results. -- Name: Steinar M. Elgsaeter (The Caveman) E-mail: elg2@nobipol.unit.no "The nice thing about C++ is that only your friends can handle your private parts."
Benny -- blee@filenet.com Tuesday, August 06, 1996 [Mini-digest: 8 responses] Try to intercept it in OnInitDialog. That should do it. Benny ---------- From: owner-mfc-l To: mfcpro; mfc-l Subject: CCheckListBox is giving me trouble! Date: Friday, August 02, 1996 7:08PM Environment: VC++ 4.0,NT 3.51 Here's my problem: - a dialog created with the dialog editor that also contains a list box - with class wizard I derived a memeber variable - CListBox m_dlListBox - in the class CMyDialog. I then changed it to a CCheckListBox-class. - in OnCreate I added this code: CRect rect; m_dlgListBox.GetItemRect(IDC_LIST, &rect); int nRet = m_dlgListBox.Create(WS_CHILD | WS_VISIBLE | LBS_STANDARD | LBS_HASSTRINGS | LBS_OWNERDRAWFIXED | LBS_OWNERDRAWVARIABLE , rect, this, IDC_LIST); ASSERT(nRet != 0); "GetItemRect(IDC_LIST, &rect);" causes the following ASSERT failure in line 643 in AFXWIN2.INL: _AFXWIN_INLINE int CListBox::GetItemRect(int nIndex, LPRECT lpRect) const { ASSERT(::IsWindow(m_hWnd)); return (int)::SendMessage(m_hWnd, LB_GETITEMRECT, nIndex, (LPARAM)lpRect); } I have discovered that this function can only be used after Create is called, but I need the parameter 'rect' it passes to run Create correctly. I can replace the second paramater 'rect' in Create with CRect(0,0, 200,200) for example and then I can see the list, although it isn't placed correctly in the dialog and seems to be hiding behind text,buttons etc. Passing NULL instead of 'rect' produces an error and trying to read the listbox-position and size from the dialog editor and passing these doesn't produce produce satisfactory results. -- Name: Steinar M. Elgsaeter (The Caveman) E-mail: elg2@nobipol.unit.no "The nice thing about C++ is that only your friends can handle your private parts." -----From: "Greg Tighe"Forget about calling Create()... that will only result in your having two separate listbox controls in your dialog. Instead, try this: m_dlgListBox.SubclassDlgItem (IDC_LIST, this); This will subclass the listbox control to your CMyCCheckListBox member variable. Make sure the 'Owner Draw:Fixed' attribute has been chosen in the dialog editor for your listbox. The listbox should be displayed with checkboxes to the left of each item. -Greg Tighe Applied Intelligent Systems, Inc. Ann Arbor, MI gdt@aisinc.com -----From: Wolfgang Loch Let the class wizard make a member variable m_List for your listbox control and change the class name in (mydlg.h) from CListBox to CCheckListBox. So why do you want to Create() it ? Wolfgang -- /-------------------------------------------------\ | Wolgang Loch (Technical University of Ilmenau) | | e-mail: Wolfgang.Loch@rz.TU-Ilmenenau.DE | | www : http://www.rz.tu-ilmenau.de/~wolo | \-------------------------------------------------/ -----From: mjmo@lubrizol.com You are doing too much work. Let MFC do most of it. In the dialog editor, make sure the listbox has these styles: owner-draw fixed Has Strings NO SORT Remove the Create from your OnCreate - the listbox will be created from your dialog template, and MFC will attach it to your CCheckListBox variable (but not until OnInitDialog). That's all you need to do. Besides the fact that you do not need to create the list box, I see two other things in your code: * There is no window handle for the control until after Create is called. So calling GetItemRect before Create will ASSERT, as you found out. But of course, that's no longer a problem because the rectangle from the dialog template will be used. * You are specifying both LBS_OWNERDRAWFIXED and LBS_OWNERDRAWVARIABLE, which I believe are mutually exclusive. One will probably override the other, but I'm not sure which. Mike Morel Mushroom Software mmorel@mushroomsoft.com MFC For Yourself at http://www.mushroomsoft.com/mushroom -----From: Gordon Weakliem I think you're trying to use a list box in a dialog, but handle it with your owner draw class. What I usually do in these cases is put a static control where the owner drawn control goes, then take the static's dimensions for my control. What it seems like you're doing is creating a secong list box on top of the one created when the dialog resource is created. I'm guessing the way your code is written, you'll get two list boxes showing up in Spy++. The reason taking units from Resource Studio is that RS deals in dialog units, not pixels. Check out GetDialogBaseUnits for details. > int nRet = m_dlgListBox.Create(WS_CHILD | >WS_VISIBLE | LBS_STANDARD | > LBS_HASSTRINGS | LBS_OWNERDRAWFIXED >| LBS_OWNERDRAWVARIABLE , > rect, this, IDC_LIST); On a side note, I don't understand why your list box is LBS_OWNERDRAWFIXED and LBS_OWNERDRAWVARIABLE. These styles are mutually exclusive; either the items are all the same size, or they aren't. Gordon Weakliem gweakl@metronet.com -----From: "Frederic Steppe" What a mess ... You don't have to create a control defined in a dialog template, it will be done for you. Of course GetItemRect doesn't work, there is no control yet ! By the way, what are you trying to do ??? If you REALLY have to move the control from its original location, you can do it in OnInitDialog (the control will exist at that time). Frederic Steppe (frederics@msn.com) -----From: "petter.hesselberg" In the original question, Steinar M. Elgsaeter (aka The Caveman) attempts to call GetItemRect on a listbox that has not yet been created. This MFC function is a wrapper for sending the message LB_GETITEMRECT to the listbox; since the listbox does not yet exist, no dice. You say that you need this rect size (which will, in fact, be the size of a single item in the listbox) to do your m_dlgListBox.Create properly. Actually, you can create it any size you want, and then use MoveWindow to set the actual position. And, by the way, OnInitDialog is generally the best place to do this sort of stuff. At that point, all the controls you drew in the dialog editor will actually have been created. Your code has a couple of other problems, though. To begin with, using IDC_LIST as the first parameter to the GetItemRect call is meaningless. This parameter is an index into the list box, not a control ID. At any rate, a CCheckListBox is normally LBS_OWNERDRAWFIXED, unless you want to handle the drawing yourself. Since it is LBS_OWNERDRAWFIXED, IDC_LIST is as good as any other index, so in this case, you'd actually get away with it -- by pure luck. You attempt to create a listbox which combines LBS_OWNERDRAWVARIABLE and LBS_OWNERDRAWFIXED styles -- these styles are not compatible. You have drawn a listbox in the dialog editor. Why do you want to create another one? That way, you will end up with two listboxes. What you want to do is to subclass the existing one; in this case, it will retain the position you gave it in the dialog editor. You should be wary of overriding variables generated by ClassWizard. It may or may not be safe in this case, but as a general rule, if I can't select a class in the ClassWizard's dialog box, I forego the Wizard on this point, define a variable for the control by hand, and use the control's CWnd::SubClass() method in OnInitDialog. FYI, the coordinates used by the dialog editor are dialog units. For more information on dialog units, check out CDialog::MapDialogUnits and all the Win32 API functions referenced there. I don't want to discourage you, but it seems to me that you have only vague ideas about what you're doing. I happen to think that MFC and ClassWizard are fine and useful tools, but you do need to have at least a rudimentary understanding of MFC, the underlying Windows API and the generated code. If you don't, you will consistently be led into the kind of quagmire you're in here. Unless you're prepared to invest a significant amount of time and effort, you'd be better off sticking with Visual Basic. Regards, Petter Hesselberg Andersen Consulting -----From: Mats Manhav You don't need to call create at all for doing this. Assume the listbox in the dialog template has the following id IDC_LIST. Declare the variable as before. Make sure that it has the style Owner drawn fixed. Then in the CYourDialog::OnInitDialog() do the following m_dlgListBox.SubclassDlgItem(IDC_LIST, this); and the listbox will be a CCheckListBox! You see, the listbox is already created by having it in the dialog template. -- ========================================================================== Mats Mеnhav (Mats Manhav for 7-bit people) email:manhav@connectum.skurup.se WWW: http://connectum.skurup.se/~manhav FAX: (int) 46 (0) 414 243 05 Phone: (int) 46 (0) 414 243 05 ==========================================================================
| Вернуться в корень Архива |