|
Hi,thanks for you kindly reply.
I want to implement the function such as: when I dropdown the list, and press DEL key, so it'll delete the highlighted item. Would you give me some advice?
Benny fun
|
|
|
|
|
I would have expected that to work no?
|
|
|
|
|
hi ther!
is it possible to implement more than 1 history comboboxes in the same dialog?
if yes, please show me how to do so? thank you very much for your time n effort!
|
|
|
|
|
I tried the folowing code:
[code]
// CDialogBar m_wndSearchBar;
// create m_wndSearchBar, pass to ReBar::AddBar, etc ...
CHistoryCombo *m_pcomboSearchQuery = (CHistoryCombo *)m_wndSearchBar.GetDlgItem(IDC_COMBO_SEARCH_QUERY);
m_pcomboSearchQuery->LoadHistory("Settings", "SearchQueryHistory");
[/code]
The last string cause assertion in CString code.
So I think I acually get CComboBox pointer not CHistoryCombo.
Is there any way to get a CHistoryCombo pointer?
I know that I can constuct CHistoryCombo directly and then pass to CReBar::AddBar()
but is I think to build all toolbars from dialog resources is more good code style.
|
|
|
|
|
If your dialog bar does not have the combo explicitly declared (and subclassed) as a CHistoryCombo then it will not be one. In fact GetDlgItem() will probably return it as a CTempWnd*. You can find out by adding a line of code like:
TRACE("Combo class = %s\n", m_pcomboSearchQuery->GetRuntimeClass()->m_lpszClassName);
To get it to be a CHistoryCombo you will at some point need to subclass it to one. You could either create your own class derived from CDialogBar and a member variable to it like:
CHistoryCombo m_combo
and then override the OnCreate in your class and do something like:
m_combo.SubclassDlgItem(IDC_COMBO_SEARCH_QUERY, this);
or, you could avoid having your own CDialogBar-derived class by handling it in the main frame, by adding the CHistoryCombo member to the CMainFrame class, and sometime after creating the dialog-bar do something like:
m_combo.SubclassDlgItem(IDC_COMBO_SEARCH_QUERY, &m_wndSearchBar);
Once you have done one of the above, you can then use m_combo to access the combo as a CHistoryCombo.
(The example in the MSDN documentation for CWnd::SubclassDlgItem shows something similar to this)
"The way of a fool seems right to him, but a wise man listens to advice" - Proverbs 12:15 (NIV)
|
|
|
|
|
I did use the last your example with SubclassDlgItem.
Its works well.
Thank you again!
|
|
|
|
|
Hi,I found that your CHistoryCombo control has some problem:When the text in the edit box of the combobox is large, the more text exceed the edit box width doesn't appear at all. Can you tell me why? Is it a bug?
liuzz
|
|
|
|
|
To allow text to be entered in the edit box of a combo that is longer than the width of the combo the CBS_AUTOHSCROLL must be used on the combo box. This is the case for all combo boxes. (My demo doesn't have this style and so text will be limited to the combo's width.)
---
"The way of a fool seems right to him, but a wise man listens to advice" - Proverbs 12:15 (NIV)
|
|
|
|
|
The problem has been solved. Thanks you!;P
liuzz
|
|
|
|
|
Is it be possible to scroll the text on the right automatically?
For example if you have long paths (e.g. D:\Program Files\Microsoft Visual Studio .NET 2003\CompactFrameworkSDK\ConnectionManager\Bin) while 'navigating' to it, would be much more useful to show the right hand side of the text (e.g. ...\CompactFrameworkSDK\ConnectionManager\Bin), rather than left part (e.g. D:\Program Files\Microsoft Visual Studio .NET 2003\...).
Can your class do this?
|
|
|
|
|
The standard combo box does this when you click on the item, or select it from the drop-list. My class is no different in this respect.
"The way of a fool seems right to him, but a wise man listens to advice" - Proverbs 12:15 (NIV)
|
|
|
|
|
Right, ok.
I was thinking more, when the drop-down is actually showing, before making the selection, the text to be moved on the right, so the right hand side of the text will be visible.
However since then the only soultion I could find was to have an owner-drawn list box, unless you have any other ideas?
Thanks.
|
|
|
|
|
Is it possible to have the same functionality here using serialization? I mean deriving a class from CComboBox and implementing serialization for the ComboBox elements. I tried to do this but my serialize() function doesn't get called and CObject's get called instead. Although, the IMPLEMENT_SERIAL() and DECLARE_SERIAL() were there.
Can any one tell my why, thanx...
|
|
|
|
|
It would help if you could post some of your code (or email it to me) so I can see how you're trying to do it. Are you using the >>/<< operators, or Serialize(ar), or ReadObject/WriteObject? I would have thought that the simplest way is to either have a CHistoryCombo::Serialize() function, and call it directly, or to have overrides of LoadHistory/SaveHistory that take a CArchive&.
---
"The way of a fool seems right to him, but a wise man listens to advice" - Proverbs 12:15 (NIV)
|
|
|
|
|
Hello Paul,
This is how i wrote the CSerialComboBox:
///////////////////////////////////////////
class CSerialComboBox : public CComboBox
{
DECLARE_SERIAL(CSerialComboBox)
// Construction
public:
CSerialComboBox();
// Attributes
public:
// Operations
public:
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CSerialComboBox)
//}}AFX_VIRTUAL
// Implementation
public:
void Serialize(CArchive& ar);
virtual ~CSerialComboBox();
// Generated message map functions
protected:
//{{AFX_MSG(CSerialComboBox)
// NOTE - the ClassWizard will add and remove member functions here.
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
// SerialComboBox.cpp : implementation file
//
#include "stdafx.h"
#include "logFilter.h"
#include "SerialComboBox.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
IMPLEMENT_SERIAL(CSerialComboBox, CComboBox, VERSIONABLE_SCHEMA )
/////////////////////////////////////////////////////////////////////////////
// CSerialComboBox
CSerialComboBox::CSerialComboBox()
{
}
CSerialComboBox::~CSerialComboBox()
{
}
void CSerialComboBox::Serialize(CArchive &ar)
{
CComboBox::Serialize(ar);
CString strTemp;
int nCount = CComboBox::GetCount();
if(ar.IsStoring())
{
for (int i=0; i <= nCount; i++)
{
CComboBox::GetLBText( i, (char*) LPCTSTR(strTemp));
ar << strTemp;
}
}
else {
}
}
BEGIN_MESSAGE_MAP(CSerialComboBox, CComboBox)
//{{AFX_MSG_MAP(CSerialComboBox)
// NOTE - the ClassWizard will add and remove mapping macros here.
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
and here how it is used in my dialog class:
void CMainDialog::OnExit()
{
CFile fSerial;
CFileException fileEx;
// fSerial.Open("presist.mus",CFile::Read
if (!fSerial.Open("presist.mus",
CFile::modeCreate | CFile::modeWrite, &fileEx))
{
PrintFileException(fileEx.m_cause);
TRACE( "File Exception: Can't creat presistance file");
exit(2); //Can't creat output file
}
CArchive arcSerial(&fSerial,CArchive::store);
CSerialComboBox *FileNames, *FilterCriteria;
FileNames = (CSerialComboBox*) GetDlgItem(IDC_FILENAME);
FilterCriteria = (CSerialComboBox*) GetDlgItem(IDC_CRITERIA);
//FileNames->Serialize(fserial);
FilterCriteria->Serialize(arcSerial);
exit(0);
}
the problem is that the Serialize() in CSerialComboBox class doesn't get called and the one in CObject which only returns. One more thing, the visual studio recognizes the CSerialComboBox but when i want to go to the funtion definitions it says that they are not defined. what might be the reason for that...
Thanx alot for your help,
Bye...
|
|
|
|
|
The main problem isn't with the serialization. It is this:
FilterCriteria = (CSerialComboBox*) GetDlgItem(IDC_CRITERIA); You can't simply cast a CWnd* to a CSerialComboBox* . Whatever you cast it to it's still really a CWnd* . If you break in a debugger after the line above, and look at what it says FilterCriteria is, it will tell you it's a CTempWnd* .
You need to subclass the control to a CSerialComboBox to be able to use it as that. This is normally done by setting up a member variable mapping using the ClassWizard. This subclasses the window handle.
When you call the MFC GetDlgItem() , the function first gets the HWND for the control, and then it looks it up to find the CWnd* it is currently mapped to (see documentation for CWnd::FromHandle ). In your case it's not mapped to anything so you get a CTempWnd object. The function then always returns it as a CWnd* .
If you had already subclassed it to a CSerialComboBox , then the pointer returned would be a CSerialComboBox* (albeit upcast to a CWnd* ), and the debugger would show it as that. (Using something like DYNAMIC_DOWNCAST can help with making sure you have the correct cast.)
So, to fix your problem, map the control to a CSerialComboBox .
As for the functions not being found, I assume you mean in the ClassView. The best remedy for this is to delete your workspace's ncb file. You will need to close the workspace first.
Perhaps I could make a suggestion about your Serialize() function. When serializing a list of items where the number of items is dynamic, it s a good idea to store the number of items first, then store each item in a loop. Then, on loading, you will then first read the number of items, then you know how many times to loop and read the actual items.
I hope this helps!
---
"The way of a fool seems right to him, but a wise man listens to advice" - Proverbs 12:15 (NIV)
|
|
|
|
|
hi Paul,
Your are right about that, I gotta subclass my combobox for it to work.
Thanx alot for your advice and happy coding..
MM.
|
|
|
|
|
I have now posted an update which includes serialising to and from a CArchive object.
"The way of a fool seems right to him, but a wise man listens to advice" - Proverbs 12:15 (NIV)
|
|
|
|
|
Doing MFC for years, I feel like a totally beginner now:
Also I get the notifications (CBN_XXX), when I select a history from the droplist, every time I query the edit control-part of the combobox for the current text (via GetWindowText) in response to such a CBN_XXX notification, it returns me the content of the edit control, as it was BEFORE the entry from the history droplist was selected.
I'm still investigating, but I don't know, whether it's related to your class or to combobox in general.
Any suggestions?
--
See me: www.magerquark.de
|
|
|
|
|
While in the handlers for the CBN_XXX notifications, the window text has not yet been updated. Therefore any call to GetWindowText() will only ever return the 'old' text. To get the newly selected text you must use:
CString sText;
int nIndex = combo.GetCurSel();
if (nIndex >= 0)
combo.GetLBText(nIndex, sText);
The only exceptions to this are for the CBN_EDITCHANGE and CBN_EDITUPDATE notifications, where you should use GetWindowText(), and not GetLBText().
(This is not related to my class; it is the same for comboboxes in general.)
---
"The way of a fool seems right to him, but a wise man listens to advice" - Proverbs 12:15 (NIV)
|
|
|
|
|
|
I would suggest to overload the functions LoadHistory and SaveHistory to be able to load/save from a string in memory, which in turn enables me to store the history in a database field.
Maybe I'll add it and post it here?!
--
See me: www.magerquark.de
|
|
|
|
|
It would be good if you could post it here. I will be updating the downloads soon with a fix for SetMaxHistoryItems, so it would be good to include your change also.
---
"The way of a fool seems right to him, but a wise man listens to advice" - Proverbs 12:15 (NIV)
|
|
|
|
|
I have posted an update which includes save to/load from a string.
"The way of a fool seems right to him, but a wise man listens to advice" - Proverbs 12:15 (NIV)
|
|
|
|
|