MFC CListbox GetItemData failed - c++

I used DrawItem() to redraw my CListbox. For some reasons, I want to use custom compare to sort my list item with my own rules, and I use LBS_SORT and no LBS_HASSTRING properties. After using SetItemData() in OnInitDialog(), I get these data in DrawItem(), but it didn't work. Code is like below:
init code :
void OnInitDialog(...)
{
.........
m_List.SetListHeight (40);
for (int i = 0 ; i < 20 ; i ++) {
m_List.AddString ((const char *) i);
m_List.SetItemData (i,(100 + i));
}
....
}
compare code :
int CompareItem(LPCOMPAREITEMSTRUCT lpCompareItemStruct)
{
ASSERT(lpCompareItemStruct->CtlType == ODT_LISTBOX);
int a = lpCompareItemStruct->itemData1;
int b = lpCompareItemStruct->itemData2;
return (a - b);
}
redraw code :
DrawItem (lpDIS)
{
..................
CString str;
int i = (int) GetItemData (lpDIS->itemID); // the i is not what I expect.
str.Format ("%d", (int) i);
dc.DrawText (str,CRect (&lpDIS->rcItem), DT_CENTER | DT_VCENTER | DT_SINGLELINE);
...................
}
when I use
***index = m_List.addstring ((const char *) i) ;
m_List.setitemdata (index,(100 + i));***
it works ,but if I use a struct to addstring ,the index is not right ,code is like this below :
struct test {
int a,b,c,d;
};
init_code :
test *ptest = new test[20]; /* just a test ,we don't delete memory till application ends */
for (int i = 0 ; i < 20 ; i ++) {
ptest [i].a = i;
int index = m_List.AddString ((const char *) (ptest + i));
m_List.SetItemDataPtr (index,(void *) (100 + i));
}
compare code :
int ListEx::CompareItem(LPCOMPAREITEMSTRUCT lpCompareItemStruct)
{
// TODO: Add your code to determine the sorting order of the specified items
// return -1 = item 1 sorts before item 2
// return 0 = item 1 and item 2 sort the same
// return 1 = item 1 sorts after item 2
// ASSERT(lpCompareItemStruct->CtlType == ODT_LISTBOX);
test *pa,*pb;
pa = (test *) lpCompareItemStruct->itemData1; // crashed here
pb = (test *) lpCompareItemStruct->itemData2;
// ASSERT (pa);
// ASSERT (pb);
return (pa->a - pb->a);
}
draw_item code :
CString str;
test *ptest = (test *) (lpDIS->itemData);
str.Format ("%d", (int) ptest->a);
dc.DrawText (str,CRect (&lpDIS->rcItem), DT_CENTER | DT_VCENTER | DT_SINGLELINE);
Is addstring can only use strings ???
if the item is a struct data ,how could I set these struct data to the listbox item ???

In OnInitDialog you should do this:
for (int i = 0 ; i < 20 ; i ++) {
int index = m_List.AddString ((const char *) i);
m_List.SetItemData (index, 100 + i);
}
AddString returns the index where the item has been inserted (which can be anywhere if the list is sorted). m_List.SetItemData (index ,(100 + i)) sets the data for the item you just have inserted.

we can set structure data to list box.
struct _empInfo {
CString strName;
..............
} empInfo = {L"XYZ",...};
m_list.AddString(empinfo.strName);
I tried above code in my app..

Related

How do you do this list operations in an efficient way in Dart (Bloc/Flutter)?

I have BLoC with the following state which contains 2 words ,
// 2 words are fixed and same length.
// in word_state.dart
abstract class WordState extends Equatable
const WordState(this.quest, this.answer, this.word, this.clicked);
final List<String> wordA; // WordA = ['B','A','L',L']
final List<String> wordB; // WordB = ['','','','']
#override
List<Object> get props => [wordA,wordB];
}
I want to ADD and REMOVE letters.
// in word_event.dart
class AddLetter extends WordEvent {
final int index;
const AddLetter(this.index);
}
class RemoveLetter extends WordEvent {
final int index;
const RemoveLetter(this.index);
}
1.ADD:
If I select the index of 'L' in wordA, then I add the letter 'L' in the first occurrence of '' (empty) in wordB.
// in word_bloc.dart
void _onLetterAdded(AddLetter event, Emitter<WordState> emit) {
final b = [...state.wordB];
b[b.indexOf('')] = state.wordA[event.index];
emit(WordLoaded(state.wordA, b));
}
//wordB, ['','','',''] into ['L','','','']
2.REMOVE:
If I deselect the index of 'L' in wordA, then I remove the last occurence of letter 'L' in wordB and shift the right side letters to left
void _onLetterRemoved(RemoveLetter event, Emitter<WordState> emit) {
final b = [...state.wordB];
final index = b.lastIndexOf(state.wordA[event.index]);
for (int i = index; i < 4 - 1; i++) {
b[i] = b[i + 1];
}
b[3] = '';
emit(WordLoaded(state.wordA, b));
}
}
// What i am trying to
// ['B','L','A','L']
// if index is 1 then ['B','A','L','']
This code is working fine, But I want to do the list operations in efficient way.
can you please check this code understand it and run it on dart pad.
List<String> wordA=['B','A','L','L'];
List<String> wordB=['','','',''];
List<String> wordBAll=['B','L','A','L'];
void main() {
wordB.insert(0,wordA[2]);
wordBAll.removeAt(wordBAll.length-1);
print(wordB);
print(wordBAll);
}

std::map pass by reference Pointer to Object

I'm coding a plugin for XPLANE10 which gets a MSG from ROS.
My IDE is QTcreator 4.1.0 based QT 5.7.0 for Ubuntu 64 Bit. I would like to use C++11 Standards
My code explained
The main initializes ROS and creates a map -> container.
ROS spins in a loop till my GUI sends a MSG where my AirPlane should fly.
The MSG contains 3 floats(phi, theta, psi) where "phi" is the AirPlane ID, theta contains the ID for my ETA(Estimated Time of Arrival)
and psi contains the ID for my pose All of the IDs are saved in the ParameterServer(lookuptable).
So at the beginning i look up the activeAirplanes which returns a vector . I would like to store them in a map where the key is the AirCraft ID and the second param is an instance of the Object.
So i have initialized the for example(looked in container while debugging):
[0] first = 1 // Airplane ID1
[0] second = new CObject(freq)
[1] first = 2 // Airplane ID2
[1] second = new CObject(freq)
If i get a MSG from GUI
phi = 1
theta=2
psi=3
,
ROS will callback
MSG(....std::map<i32, CObject> &container)
// if phi is 1 so use the mapkey 1 and trigger the method do_stuff from CObject
do_stuff(phi, theta, psi,freq)
I would like to call the in a function from main
int getPlanes(std::map<i32,CObject>& container)
{
...
getActiveAirplanesFromServer(activePlanes);
}
First Question:
How do i pass the container to my callback?
Second Question:
How do i parallelize do_stuff() so my callback will return to main and i'm able to command more aircrafts while the others are calculated?
Third Question:
How would be the correct syntax for getPlanes to pass the container by reference so getPlanes() can edit it?
Fourth Question:
Is there a difference between
std::map<i32,CObject*> map
std::map<i32,CObject>* map
and
std::map<i32,CObject*>::iterator it=container->begin();
std::map<i32,CObject*>::iterator* it=container->begin();
If yes, what do i want ? #4Solved
// I have to edit stuff 'cause of some restrictions in my company.
#include "Header.h"
int main()
{
f64 freq = 10;
std::map<i32, CObject>* container;
std::map<i32,CObject>::iterator* it=container->begin();
// ROS
if(!ros::isInitialized())
{
int rosargc = 0;
char** rosargv = NULL;
ros::init(rosargc, rosargv, "MainNode");//), ros::init_options::AnonymousName);
}
else
{
printf("Ros has already been initialized.....\n");
}
ros::NodeHandle* mainNodeHandle=new ros::NodeHandle;
ros::AsyncSpinner spinner(2);
ParameterServer * ptrParam= new ParameterServer(mainNodeHandle);
ros::Subscriber airSub=mainNodeHandle->subscribe<own_msgs::ownStruct>("/MSG",
1000,
boost::bind(MSG,
_1,
freq,
container));
std::vector<i32> activePlanes;
i32 retVal=0;
retVal += ptrParam-> ParameterServer::getActiveAirplanesFromServer(activePlanes);
if (retVal == 0 && activePlanes.size()>0)
{
for (u32 j =0; j <activePlanes.size(); j++)
{
container->insert (std::pair<i32,CObject> (activePlanes[j] , new CObject(freq)));
}
}
while (ros::ok())
{
spinner.start(); //spinnt sehr viel :-)
ros::waitForShutdown ();
}
std::cout<<"ENDE"<<std::endl;
int retval = 1;
return retval;
}
void MSG(const own_msgs::ownStruct<std::allocator<void> >::ConstPtr &guiMSG,
f64 freq,
std::map<i32, CObject> &container)
{
if ((guiMSG->phi != 0) && (guiMSG->theta != 0) && (guiMSG->psi != 0))
{
std::string alpha = std::to_string(guiMSG->phi)+std::to_string(guiMSG->theta)+to_string(guiMSG->psi);
container.at(guiMSG->phi) -> do_stuff(guiMSG->phi,guiMSG->theta,guiMSG->psi, freq);
}
else
{
std::cout<<" Did not receive anything\n"<<endl;
}
}
void do_stuff(...)
{
//copy the IDs to private Member of this single Object
//setROS() for this single Object
//callback the current AC pose via ID from XPLANE
//callback the wished AC pose via ID from ParamServer
// do some calculations for optimum flight path
// publish the Route to XPlane
}
EDIT::
Problem is i get it to compile now and if debug it and set a breakpoint at :
void MSG(const own_msgs::ownStruct<std::allocator<void> >::ConstPtr &guiMSG,f64 freq,std::map<i32, CObject*> &container)
{
..
/*->*/ container.at(guiMSG->)...
}
The Container remains empty.
So i read some stuff about pointers and i saw my errors..
I confused * and &
if i want to pass the adress of a variable i have to write like
int main()
{
int a = 0;
AddTwo(&a)
cout<<a<<endl; // Output: 2
}
void AddTwo(int* a)
{
a+=2;
}

Output formatted text to Screen

I have a vector that stores pairs. Each pair contains a CString and a bool.
If the CString is meant to be underlined then bool is true, else it is false.
I want to output the text in the vector to the screen making sure that text is underlined in the correct places.
So far I have the following code:
void CEmergenceView::AppendText( CString msg ) {
int nBegin;
CRichEditCtrl &rec = GetRichEditCtrl();
nBegin = rec.GetTextLength();
rec.SetSel(nBegin, nBegin); // Select last character
rec.ReplaceSel(msg); // Append, move cursor to end of text
rec.SetSel(-1,0); // Remove Black selection bars
nBegin = rec.GetTextLength(); // Get New Length
rec.SetSel(nBegin,nBegin); // Cursor to End of new text
// Fix annoying "do you want to save your changes?" when program exits
GetDocument()->SetModifiedFlag(FALSE); // -Optional- (sometimes you want this)
}
int nEnd = 0;
// loop through start of text to end of text
for(int k = 0; k < groups.size(); k++) {
rEditCtrl.SetSel(nEnd, nEnd);
rEditCtrl.GetSelectionCharFormat(cf);
if(groups.at(k).second) {
if(!cf.dwEffects & !CFE_UNDERLINE) {
CRichEditView::OnCharUnderline();
}
}
else if(!groups.at(k).second) {
if(cf.dwEffects & CFE_UNDERLINE) {
CRichEditView::OnCharUnderline();
}
}
AppendText(groups.at(k).first);
nEnd = nEnd + (groups.at(k).first.GetLength());
}
However, this is not underlining at all....Can anyone tell me what I'm doing wrong?? Thanks!
I think you should implement the OnCharUnderline
Try to call yours own function instead of the default one:
You can get it from here:
void CMyRichEditView::OnCharUnderline ()
{
CHARFORMAT2 cf;
cf = GetCharFormatSelection();
if (!(cf.dwMask & CFM_UNDERLINE) || !(cf.dwEffects & CFE_UNDERLINE))
cf.dwEffects = CFE_UNDERLINE;
else
cf.dwEffects = 0;
cf.dwMask = CFM_UNDERLINE;
SetCharFormat(cf);
}

std::list copy to std::vector skipping elements

I've run across a rather bizarre exception while running C++ code in my objective-C application. I'm using libxml2 to read an XSD file. I then store the relevant tags as instances of the Tag class in an std::list. I then copy this list into an std::vector using an iterator on the list. However, every now and then some elements of the list aren't copied to the vector. Any help would be greatly appreciated.
printf("\n length list = %lu, length vector = %lu\n",XSDFile::tagsList.size(), XSDFile::tags.size() );
std::list<Tag>::iterator it = XSDFile::tagsList.begin();
//result: length list = 94, length vector = 0
/*
for(;it!=XSDFile::tagsList.end();++it)
{
XSDFile::tags.push_back(*it); //BAD_ACCESS code 1 . . very bizarre . . . . 25
}
*/
std::copy (XSDFile::tagsList.begin(), XSDFile::tagsList.end(), std::back_inserter (XSDFile::tags));
printf("\n Num tags in vector = %lu\n", XSDFile::tags.size());
if (XSDFile::tagsList.size() != XSDFile::tags.size())
{
printf("\n length list = %lu, length vector = %lu\n",XSDFile::tagsList.size(), XSDFile::tags.size() );
//result: length list = 94, length vector = 83
}
I've found the problem. The memory was corrupted causing the std::list to become corrupted during the parsing of the XSD. I parse the XSD using a function start_element.
xmlSAXHandler handler = {0};
handler.startElement = start_element;
I used malloc guard in xcode to locate the use of freed memory. It pointed to the line:
std::strcpy(message, (char*)name);
So I removed the malloc (actually commented in the code) and it worked. The std::vector now consistently copies all 94 entries of the list. If anyone has an explanation as to why this worked that would be great.
static void start_element(void * ctx, const xmlChar *name, const xmlChar **atts)
{
// int len = strlen((char*)name);
// char *message = (char*)malloc(len*sizeof(char));
// std::strcpy(message, (char*)name);
if (atts != NULL)
{
// atts[0] = type
// atts[1] = value
// len = strlen((char*)atts[1]);
// char *firstAttr = (char*)malloc(len*sizeof(char));
// std::strcpy(firstAttr, (char*)atts[1]);
if(strcmp((char*)name, "xs:include")==0)
{
XSDFile xsd;
xsd.ReadXSDTypes((char*)atts[1]);
}
else if(strcmp((char*)name, "xs:element")==0)
{
doElement(atts);
}
else if(strcmp((char*)name, "xs:sequence")==0)
{
//set the default values
XSDFile::sequenceMin = XSDFile::sequenceMax = 1;
if (sizeof(atts) == 4)
{
if(strcmp((char*)atts[3],"unbounded")==0)
XSDFile::sequenceMax = -1;
int i = 0;
while(atts[i] != NULL)
{
//atts[i] = name
//atts[i+i] = value
std::string name((char*)atts[i]);
std::string value((char*)atts[i+1]);
if(name=="minOccurs")
XSDFile::sequenceMin = (atoi(value.c_str()));
else if(name=="maxOccurs")
XSDFile::sequenceMax = (atoi(value.c_str()));
i += 2;
}
}
}
}
//free(message);
}

COleSafeArray / VARIANT memory leak?

I want to export a lot of (table) data to Excel. I'm developing on Windows Xp, Vs2005. I'm filling a COleSafeArray, which was initialized like this:
safeArray.Create( VT_VARIANT, 2, numElements ); // 2 dimensional, 30000 rows, 3 columns
Now the filling is really fast, but in TaskManager/Process Explorer/VMMap, it looks like some of the memory does not get released properly (VMMap still finds my dummy strings in the memory). I tried the tips (disabling BSTR caching) from the following pages, but had no success so far:
https://devblogs.microsoft.com/oldnewthing/20091127-00/?p=15883
http://blogs.msdn.com/larryosterman/archive/2004/09/28/235304.aspx
Is there still the caching taking place (I've set the environment variable OANOCACHE = 1), or is there something wrong with my code?
Note: This is part of a MFC dialog based non-unicode application.
//-----------------------------------------------------------------------------
template< typename _ValueType >
void setSafeArrayElement( const _ValueType& value,
const int row,
const int column,
COleSafeArray& safeArray
)
{
VARIANT variant;
VariantInit(&variant);
{
COleVariant oleVariant = value;
variant = oleVariant;
oleVariant.Detach();
}
long coordinates[2] = { row, column };
safeArray.PutElement( coordinates, &variant );
VariantClear(&variant);
}
//-----------------------------------------------------------------------------
#define XL_CELLTYPE_TEXT "#"
#define XL_CELLTYPE_DOUBLE2 "#'##0.00"
#define XL_CELLTYPE_DOUBLE3 "#'##0.000"
#define XL_CELLTYPE_DOUBLE4 "#'##0.0000"
#define XL_CELLTYPE_DOUBLE6 "#'##0.000000"
#define XL_CELLTYPE_DOUBLE8 "#'##0.00000000"
#define XL_CELLTYPE_NUMBER "0"
#define XL_CELLTYPE_NUMBER1000 "#'##0"
#define XL_CELLTYPE_DATE "TT.MM.JJJJ"
#define XL_CELLTYPE_GENERAL "Standard"
//-----------------------------------------------------------------------------
void CexcelTestDlg::OnBnClickedButton2()
{
const bool closeExcel = true;
const int rows = 30000;
const int columns = 3;
//AfxOleGetMessageFilter()->SetMessagePendingDelay( x );
AfxOleGetMessageFilter()->EnableNotRespondingDialog( FALSE );
AfxOleGetMessageFilter()->EnableBusyDialog( FALSE );
Excel11::_ApplicationPtr app;
Excel11::WorkbooksPtr books;
Excel11::_WorkbookPtr book;
Excel11::SheetsPtr sheets;
Excel11::_WorksheetPtr sheet;
app.CreateInstance( "Excel.Application" );
try
{
//app->Visible = VARIANT_TRUE;
app->Visible = VARIANT_FALSE;
app->Interactive = VARIANT_FALSE;
app->UserControl = VARIANT_FALSE;
app->ScreenUpdating = VARIANT_FALSE;
app->DisplayAlerts = VARIANT_FALSE;
books = app->GetWorkbooks(); // all open files
book = books->Add(); // add new file
sheets = book->Sheets; // all worksheets
try
{
COleSafeArray safeArray;
DWORD numElements[] = { rows, columns };
safeArray.Create( VT_VARIANT, 2, numElements );
// rename default worksheet
Excel11::_WorksheetPtr
sheet1 = sheets->GetItem(1);
sheet1->Name = "Blah";
// format columns
{
std::string coords = getExcelCoordinates( 0, 0 ); // getExcelCoordinates returns strings like "A1", "F23", ... (excel cell coordinates)
Excel11::RangePtr range = sheet1->Range[coords.c_str()][coords.c_str()];
range = range->EntireColumn;
range->NumberFormat = XL_CELLTYPE_TEXT;
coords = getExcelCoordinates( 0, 1 );
range = sheet1->Range[coords.c_str()][coords.c_str()];
range = range->EntireColumn;
range->NumberFormat = XL_CELLTYPE_DATE;
coords = getExcelCoordinates( 0, 2 );
range = sheet1->Range[coords.c_str()][coords.c_str()];
range = range->EntireColumn;
range->NumberFormat = XL_CELLTYPE_DOUBLE2;
}
// fill line by line
for( int row = 0; row < rows; ++row )
{
CString rowName;
rowName.Format( "%d", row + 1 );
// Text
CString v0 = CString( "Wusel Dusel " ) + rowName;
setSafeArrayElement( v0, row, 0, safeArray );
// Date
CString v1 = "11.12.1975";
setSafeArrayElement( v1, row, 1, safeArray );
// Number
double v2 = 123.45;
setSafeArrayElement( v2, row, 2, safeArray );
}
// export safearray to excel
if( rows )
{
const std::string cellCoordTopLeft = getExcelCoordinates( 0, 0 );
const std::string cellCoordBottomRight = getExcelCoordinates( rows-1, columns-1 );
Excel11::RangePtr range = sheet1->Range[ cellCoordTopLeft.c_str(), cellCoordBottomRight.c_str()];
COleVariant vtOptional((long)DISP_E_PARAMNOTFOUND,VT_ERROR);
// export the whole safeArray contents to excel
range->PutValue( vtOptional, COleVariant( safeArray ) );
}
// optimize column widths
Excel11::RangePtr cells = sheet1->Cells;
cells->Select();
cells->EntireColumn->AutoFit();
Excel11::RangePtr singleCell = sheet1->Range["A1"]["A1"];
singleCell->Select();
// clear safeArray
VARIANT* varPtr = 0;
try
{
// Get a pointer to the elements of the array
// and increments the lock count on the array
safeArray.AccessData((LPVOID*)&varPtr);
for( int i = 0; i < rows * columns; ++i )
{
VARIANT& vp = varPtr[i];
VariantClear( &vp );
}
//decrement lock count
safeArray.UnaccessData();
}
catch (COleException *pEx)
{
AfxThrowOleDispatchException(1003, _T("Unexpected Failure in FastSort method"));
pEx->Delete();
}
//safeArray.DestroyData(); //???
//safeArray.DestroyDescriptor(); //???
safeArray.Clear();
}
catch( std::exception& err )
{
MessageBox( err.what() );
}
if( closeExcel )
{
book->Close( VARIANT_FALSE ); // close the file
app->Quit(); // close Excel instance
}
else
{
app->Visible = VARIANT_TRUE;
app->Interactive = VARIANT_TRUE;
app->UserControl = VARIANT_TRUE;
app->ScreenUpdating = VARIANT_TRUE;
app->DisplayAlerts = VARIANT_TRUE;
}
app.Release();
}
catch( _com_error& err )
{
CString s(err.Description().GetBSTR());
MessageBox(s);
}
}