Adding items to a list



  • Hi guys, I am an advanced C# coder who is trying to transition over to real coding in C++ but getting stuck on some hurdles, which normally would be easy in C#.

    Here is what I am trying to do:

    @
    MyForm::MyForm(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::MyForm)
    {
    ui->setupUi(this);
    ui->myList->clear();
    if (createProcessList())
    {
    list<ProcInfo>::const_iterator p;
    for (p=procList.begin();p!=procList.end(); ++p)
    {
    ui->myList->addItems(*p);
    }
    }
    }
    @

    In C# this would work by using the base string To.String() to name the items when adding to a list, however here it seems alot different and I cannot figure it out.

    Any help would be appreciated. Thanks.

    Edit: Forgot to mention, procList is a list of processes already generated elsewhere in the application:

    @
    list<ProcInfo> procList;
    @



  • Well if there's no implicit conversion from your ProcInfo class to QString, you'd have to call the appropriate method yourself e.g.
    @
    ui->myList->addItem((*p).name());
    @
    Also, in your snippet you use addItems, while (I guess), it should be addItem.



  • Hi, I seem to get a compile error:

    error: 'const class ProcInfo' has no member named 'name'.

    I'm guessing I have to create the method, in which case how would one create a QString method inside the ProcInfo class?



  • Of course! Adapt that snippet to what you're actually doing!

    What's your ui->myList? And what's a ProcInfo?



  • myList is a listbox widget on the app, and ProcInfo:

    @class ProcInfo
    {
    public:
    HANDLE Proc;
    DWORD Base;
    int ID;
    };@



  • And exactly what do you want to add to that list? Because there's nothing resembling a string inside your ProcInfo class...



  • I want to add each ProcInfo contained in the list to the listbox, but from your repsonse I am guessing you can't add custom class items to a listbox the same way you can in C#.



  • even in C# you need to have a ToString method. How would C++ what you actually want to print. That being said. What do you want to print? The id? In that case you could have an implicit cast to QString like:
    @
    class ProcInfo
    {
    public:
    //code
    operator QString() const
    {
    return QString::number(id);
    }
    };
    @
    or you could call QString::number in the loop instead of adding an implicit cast function:
    @
    ui->myList->addItem(QString::number((*p).id));
    @



  • [quote author="loladiro" date="1312196973"]even in C# you need to have a ToString method. How would C++ what you actually want to print. [/quote]

    No you don't in C#, because when you create a class it automatically has a base ToString() method which is automatically used in certain controls like listboxes without being called (although the string would be simply the class name unless you override the method) I assumed C++ would be no different but clearly it is.

    Thanks for the help.



  • How would I use your operator QString() const method? I can tell I have a long way to go int he conversion from C# to C++ :(



  • Sorry, I forgot about that in C# (I have only once looked into it and that very briefly). However, if you consider your issue solved, pleas add [Solved] in front of the thread title (by editing the first post).



  • I can't work out actually how to use your operator QString() const.



  • The posts must have crossed in the air ;). The QString() const method is an "explicit coversion operator":http://msdn.microsoft.com/en-us/library/ts48df3y(v=vs.80).aspx . However, be aware that there are also many bugs that may follow from the misuse of this laguage feature.

    EDIT: you can use it just like ou would in C# (i.e. without doing anything special)



  • That's what I thought but get compiler error:

    error: no matching function for call to 'QListWidget::addItem(const ProcInfo&)'



  • Actually there are more compile errors I should have mentioned which are most likely causing this:

    error: no match for 'operator=' in 'p = procList.std::list<_Tp, _Alloc>::begin with _Tp = int, _Alloc = std::allocator<int>'



  • Sorry but I can't reproduce. This all works:
    @
    class ProcInfo
    {
    public:
    int id;
    ProcInfo() : id(1234)
    {}
    operator QString() const
    {
    return QString::number(id);
    }
    };

    void print(QString print)
    {
    qDebug() << print;
    }

    int main(int argc, char *argv[])
    {
    QApplication a(argc, argv);

    QList< ProcInfo > list1;
    list1 << ProcInfo();
    QList< ProcInfo >::const_iterator i = list1.begin();
    
    std::list< ProcInfo > list2;
    list2.push_back(ProcInfo());
    
    std::list< ProcInfo >::const_iterator i2 = list2.begin();
    
    print(*i2);
    
    print (*(i));
    
    QListWidget widget;
    widget.addItem(*i);
    
    std::list< ProcInfo >::const_iterator p = list2.begin();
    
    for (p=list2.begin();p!=list2.end(); ++p)
    {
        widget.addItem(*p);
    }
    
    widget.show();
    
    const ProcInfo p2;
    print(p2);
    
    return a.exec(&#41;;
    

    }
    @



  • Ok I've managed to get rid of all compile errors except this one:

    error: expected type-specifier before 'QString'

    And the error points to the operator:

    @
    class ProcInfo
    {
    public:
    HANDLE Proc;
    DWORD Base;
    int ID;
    operator QString() const
    {
    return QString::number(ID);
    }
    };@



  • did you #include <QString>?



  • That fixed that but now I have another problem /sigh.

    I have declared std::list<ProcInfo> procList; inside a header file, and that header file is included in the main cpp file which I am doing this all in, however I get error:

    error: multiple definition of `procList'

    There is definitely only 1 definition and it's inside the h file so I'm a little confused, maybe c++ isn't for me :(



  • There's not much we can do without seeing the header file ...



  • proc.h

    @
    #include <windows.h>
    #include <list>
    #include <QString>

    #ifndef PROC_H
    #define PROC_H

    #endif // PROC_H

    class ProcInfo
    {
    public:
    HANDLE Proc;
    DWORD Base;
    int ID;
    operator QString() const
    {
    return QString::number(ID);
    }
    };

    std::list< ProcInfo > procList;

    bool createProcessList();
    DWORD GetModuleBase(LPSTR lpModuleName, DWORD dwProcessId);
    @

    proc.cpp

    @
    #include <windows.h>
    #include <iostream>
    #include <string>
    #include <tlhelp32.h>
    #include "proc.h"
    #include "misc.h"

    using namespace std;

    bool createProcessList()
    {
    PROCESSENTRY32 entry;
    entry.dwSize = sizeof(PROCESSENTRY32);

    HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL);
    
    if (Process32First(snapshot, &entry;) == TRUE)
    {
        while (Process32Next(snapshot, &entry;) == TRUE)
        {
            char *procName;
            strcpy_wc(procName, entry.szExeFile);
            if (stricmp(procName, "pol") == 0)
            {
                ProcInfo *p = new ProcInfo();
                p->Proc = OpenProcess(PROCESS_ALL_ACCESS,FALSE,entry.th32ProcessID);
                p->ID = entry.th32ProcessID;
                p->Base = GetModuleBase("test.dll", entry.th32ProcessID);
                procList.push_back(*p);
            }
        }
        if (procList.empty())
           return false;
        return true;
    }
    
    CloseHandle(snapshot);
    return 0;
    

    }

    DWORD GetModuleBase(LPSTR lpModuleName, DWORD dwProcessId)
    {
    MODULEENTRY32 lpModuleEntry = {0};
    HANDLE hSnapShot = CreateToolhelp32Snapshot( TH32CS_SNAPMODULE, dwProcessId );
    if(!hSnapShot)
    return NULL;
    lpModuleEntry.dwSize = sizeof(lpModuleEntry);
    BOOL bModule = Module32First( hSnapShot, &lpModuleEntry; );
    while(bModule)
    {
    char *foundModule;
    strcpy_wc(foundModule, lpModuleEntry.szModule);
    if(!strcmp( foundModule, lpModuleName ) )
    {
    CloseHandle( hSnapShot );
    return (DWORD)lpModuleEntry.modBaseAddr;
    }
    bModule = Module32Next( hSnapShot, &lpModuleEntry; );
    }
    CloseHandle( hSnapShot );
    return NULL;
    }
    @

    That error points to line 11 in proc.cpp.



  • Well, my first comment is: fix your "include guards":http://en.wikipedia.org/wiki/Include_guard



  • I'll be honest, I don't really get it :/



  • Yes! Let me explain. In C (and C++) an #include directive will include the file regardless of whether it has been included before. You can litterally compare this to copy'n'past-ing the header file into the source code whenever there is an #include directive. The include guards are used to make sure every header file is only included once. E.g. if your header file would usually be
    @
    class Dummy
    {};
    @
    you'd have to use
    @
    #ifndef DUMMY_H //i.e. if dummy.h has never been included before
    #define DUMMY_H //remember that it has been included

    class Dummy
    {};

    #endif //endif after all statements
    @
    In your case the include guards have to enclose all of your statements (the header files not necessarily because they have their own include guards, but it's usually best to have the include guards be the first and last satements in your header files)



  • Ok so if I understand you it should be:

    @
    #include <windows.h>
    #include <list>
    #include <QString>

    #ifndef PROC_H
    #define PROC_H

    class ProcInfo
    {
    public:
    HANDLE Proc;
    DWORD Base;
    int ID;
    operator QString() const
    {
    return QString::number(ID);
    }
    };

    std::list<ProcInfo> procList;

    bool createProcessList();
    DWORD GetModuleBase(LPSTR lpModuleName, DWORD dwProcessId);

    #endif // PROC_H@

    But I still get the same error.



  • In the compiler output window there should be information about where the compiler thinks that procList has been declared (something like "previously declared here: " )



  • c:\QtSDK\Desktop\Qt\4.7.3\mingw\include\QtCore\qatomic_i386.h:125: error: first defined here



  • Hmm... try to use
    @ inline operator QString() const
    {
    return QString::number(ID);
    }
    @



  • Same error :( The error is on procList anyways not ProcInfo, it doesn't make alot of sense to me :/



  • If you wish procList in header, you need to declare it in cpp file, and define in header as
    @extern std::list< ProcInfo > procList@



  • Guys. It's not a "try and guess" process. He defined a global variable inside a header. As soon as that header gets included in two or more translation units, the compiler will output multiple definitions of the same name. And the linker will complain. Put that definition in ONE translation unit and you'll be ok.



  • Works thanks :) But now I have other unrelated questions, should I post in a separate thread?



  • Yep, You do. One theme - one thread.



  • I have another question about this.

    The function currently working is:

    @
    class ProcInfo
    {
    public:
    HANDLE Proc;
    DWORD Base;
    std::string WindowName;
    int ID;
    inline operator QString() const
    {
    return QString::number(ID);
    }
    };
    @

    How would I mane the QString method return the following format:

    "(" + ID + ") " + WindowName

    So the output would end up something like:

    (432) NotePad



  • @
    return QString('(') + QString::number(ID) + ')' + WindowName.c_str()
    @
    Also have a look at "More Efficient String Construction":http://doc.qt.nokia.com/latest/qstring.html#more-efficient-string-construction


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.