What is the use of CListCtrl::GetItemData()? - winapi

Can anybody please help me to know, what is the use of CListCtrl::GetItemData() in MFC, VC++ ?
I went through MSDN description but it was not clear enough.
If anybody can provide a brief explanation and some example it will be really great and would help a lot.

The item data allows you to associate any data you want to each item of your list control. This data is most of the time a pointer to some data structure.
For example in an email application you have a list control containing all received emails. Each item contains for example the sender, the subject and the date. The item data would contain a pointer to some data structure which contains the whole mail text amoung other information.

The method GetItemData() is used in association with the method SetItemData() to allow a CListCtrl or a CTreeCtrl to have associated with items or nodes in the control some data.
The idea is that when populating the list or tree with nodes you can also assign a data item to the node using SetItemData() which can be retrieved by using GetItemData() when processing a selection event. The associated data may be something like a pointer to an object or an identifier of some sort which is the key to data stored in a collection such as a std::map.
The data type for the value retrieved with GetItemData() or assigned to an item with SetItemData() is a DWORD_PTR (see DWORD and DWORD_PTR on 64 bit machine for a discussion on DWORD_PTR).
Another coincidence is that the SendMessage() and PostMessage() Windows API function have the LPARAM parameter, e.g. SendMessage(HWND hWnd, UINT uiMsg, WPARAM wParam, LPARAM lParam)which is the same size as a LONG_PTR which is a long on x32 compile or __int64 on x64 compiles (see Microsoft Docs - Windows Data Types). And a DWORD_PTR is the same as a ULONG_PTR which just so happens to be a unsigned long on x32 compile or unsigned __int64 on x64 compiles.
This means that the DWORD_PTR value from GetItemDataa() can be used as the LPARAM value in a SendMessage() or PostMessage(). So you could use the SetItemData() method to associate a LPARAM type of identifier that the handler for a selection event for a CListCtrl or CTreeCtrl can then send to some other window or thread whose handle is known to communicate the selection event to some other part of the application.

Solution for beginners
For example, you have an int / string /struct or something else
struct foo
{
...
};
foo myData;
list.SetItemData(nItem, reinterpret_cast<DWORD_PTR>(&myData));
...
myData = *(reinterpret_cast<foo*>(list.GetItemData(nItem)));
Note that SetItemData accepts a reference to an object, the object must be global,otherwise it will be destroyed

Related

Handling the hook function

I'm trying to use EasyHook in C# to properly hook into a method from a COM object (unmanaged).
I was able to determine the address of the method of the COM object and I can properly trigger my hook function. I did it this way, being the rest of the code pretty much similar to the one in the tutorial:
SendHook = LocalHook.Create(0x12345678, new DMyFunc(MyFunc_Hooked), this);
However, once inside my hook, all parameters are scrambled (they do not equal those that I'm originally passing).
Also, I'm not able to return anything (please note that I also tried hooking another function that returns a short and the value doesn't properly return).
When I open eXescope, this is one of the function signatures:
function MyFunc(out ParamA:^BSTR; out ParamB:^bool): ^TypeA;
And this function has the following signature when I use the COM object normally in C#:
TypeA MyFunc(ref string ParamA, ref bool ParamB);
Any ideas? Thanks in advance!
I managed to solve the problem in 5 minutes after reading the article provided by Dark Falcon. I totally recommend reading it! Therefore, all credit for the answer goes to him!

release event.data.ptr when epoll_ctl(del) a fd

I use event.data.ptr to point to an object.
When I epoll_ctl(del) the event I have to delete the object(pointed by event.data.ptr).
How can I get the pointer?
epll_ctl(del) just ignores the parameter 'event':
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
Do I have to maintain a vector of these objects? I think its a little dirty.
thanks.
it is in fact. There is no way to query the data field in the epoll interface. The common workaround is to keep that data in your own list in user-space.
I think its time someone write an epoll syscall to query that field to avoid duplicated data associated to a file descriptor.

Simple hierarchical listing in PyQT

I'm trying to create a UI with 3 columns - when you select an item in the left column, the select item is passed to a function, and it returns the items for the middle column (and of course same for selecting items in the middle column)
Should be simple, but I can't find any easy way to do this..
I first tried QColumnView, as it seemed perfect.. however implementing the QAbstractItemModel seems excessively complicated, and I couldn't find any useful examples of this.
Next, since there is a fixed number of levels, I made three QListView, and modified this example QAbstractListModel
..however there seemed to be no useful signal I could use to trigger the updating of the other levels of the hierarchy. According to the PyQT docs, QListView only has the "indexesMoved" signal. There is also "clicked" and "pressed", however these didn't trigger when changing items with the keyboard
The last options is QListWidget, which would work as it has the required signals (itemChanged etc), but the way list items are created is a bit tedious (making QListWidgetItem with the parent set to the QListWidget instance)
Edit: QListWidget does pretty much what I need:
self.first_column = QListWidget()
self.first_column.itemSelectionChanged.connect(self.update_second_column)
Any QAbastractItemView has a QItemSelectionModel accessible via the selectionModel method.
The QItemSelectionModel has signals that may help you:
currentChanged ( const QModelIndex & current, const QModelIndex & previous )
currentColumnChanged ( const QModelIndex & current, const QModelIndex & previous )
currentRowChanged ( const QModelIndex & current, const QModelIndex & previous )
selectionChanged ( const QItemSelection & selected, const QItemSelection & deselected )
Hope it helps.
QListView inherits from QAbstractItemView (I think you knew this), so it gets a few signals, hopefully one (or a few) of them works for you.
This is working for me (connect signals when initializing your QMainWindow or main QWidget, as in the SaltyCrane example):
connect(your_list_view, SIGNAL("clicked(const QModelIndex&)"), handler_slot)
...
def handler_slot(idx):
#idx is a QModelIndex
#QModelIndex.data() returns a QVariant, Qt4's generic data container
celldata = idx.data()
#Choose the proper datatype to ask the QVariant for (e.g. QVariant.toInt())
actualvalue = celldata.toInt()
#QVariant.toInt() happens to return a tuple
print actualvalue[0]
Depending on the type of data in your model, you'll want to choose the right data type to ask QVariant for.
The sneaky part here is getting the QListView to tell you which cell was clicked (i.e. using clicked(const QModelIndex&) vs clicked()). I think I spent some time looking at the C++ documentation for Qt4 before I realized you could get more out of the signals.
From here, I would have the handler_slot() call a setData() method on the model for your second QListView (using data generated by the function you originally planned to use).
I'd be glad to elaborate if I haven't quite answered your question.
Edit: Working with arrow keys
Hmm, it seems weird that there isn't a default QListView signal for arrow movement, but we can make our own.
(This almost seems out-of-style for Qt4's signals and slots modus operandi)
QListView reimplements a method keyPressEvent(self, QKeyEvent) which acts as a callback function when certain keys are pressed. You can read more. We can use this to grab the keyevent(s) that we want, and emit our own signal.
class ArrowableListView(QListView):
def keyPressEvent(self, keyevent):
#Maintain original functionality by calling QListView's version
QListView.keyPressEvent(self, keyevent)
#QListView.selectedIndexes returns a list of selected cells, I'm just taking the first one here
idx = self.selectedIndexes()[0]
#We'll emit a signal that you can connect to your custom handler
self.emit(SIGNAL("my_signal"), idx)
Once a keypress occurs, we ask the QListView what the selected indices (!) are. Of course, you can choose to filter out certain keys and choose whether to handle multiple selected cells (I think you can set a selection mode where this isn't possible, see QListView documentation).
Now that we have the selected indices (list of QModelIndex), we pass the first one (a QModelIndex) along with our signal. Because we're defining this signal in python, we don't have to set a function prototype; I have no idea if this is bad style.
Now all you have to do is connect the signal to a handler:
self.connect(your_list_view, SIGNAL("my_signal"), handler_slot)
and write your handler.
I hope this isn't too nasty of a workaround.

How to create dynamic Callbacks in MATLAB?

I have this line of code:
delete_btn = uicontrol(rr_ops, 'Style', 'pushbutton', 'String', 'Delete Graphic', 'Position', [13 135 98 20], ...
'Callback', 'delete_graphic');
and a little bit upper this function:
function delete_graphic
global rr_list
selected = get(rr_list, 'Value');
selected
return;
why this code is not working? I really dont understand...
What do I need? I create one button and a listbox, clicking on button - deleting selected element from a listbox.
Thx for help.
PS
Always getting this error:
??? Undefined function or variable 'delete_graphic'.
??? Error while evaluating uicontrol Callback
here is all my code: http://paste.ubuntu.com/540094/ (line 185)
The generally-preferred way to define a callback function is to use a function handle instead of a string. When you use a string, the code in the string is evaluated in the base workspace. This means that all the variables and functions used in the string have to exist in the base workspace when the callback is evaluated. This makes for a poor GUI design, since you don't really want the operation of your GUI dependent on the base workspace (which the user can modify easily, thus potentially breaking your GUI).
This also explains the error you are getting. The function delete_graphic is defined as a subfunction in your file rr_intervals.m. Subfunctions can only be called by other functions defined in the same m-file, so delete_graphic is not visible in the base workspace (where your string callback is evaluated). Using a function handle callback is a better alternative. Here's how you would do it:
Change the callback of your button (line 216) from 'delete_graphic' to #delete_graphic.
Change the function definition of delete_graphic (line 185) to:
function delete_graphic(hObject,eventdata)
where hObject is the handle of the object issuing the callback and eventdata is optional data provided when the callback is issued.
EDIT:
If you want to pass other arguments to delete_graphic, you can perform the following steps:
Add the additional input arguments to the end of the function definition. For example:
function delete_graphic(hObject,eventdata,argA,argB)
Use a cell array when you set the callback for your button, where the first cell contains the function handle and the subsequent cells each contain an input argument. For example:
set(delete_btn,'Callback',{#delete_graphic,A,B});
There is one caveat to this, which is that the values A and B stored in the cell array are fixed at what they are when you set the callback. If you change A or B in your code it will not change the values stored in the cell-array callback.
If you aren't able to use the above solution (i.e. if A and B need to change value), there are a few other options for how you can share data among a GUI's callbacks:
You can rework the organization of your code to make use of nested functions. This makes it very easy to share data between callbacks. Some nice examples of using nested functions to create GUIs can be found in the MathWorks File Exchange submission GUI Examples using Nested Functions by Steven Lord.
You can store data in the UserData property of a uicontrol object. To access or update it, you just need the object handle.
You can use the functions SETAPPDATA/GETAPPDATA to attach data to a handle graphics object (i.e. uicontrol).
Since it appears your code was created using GUIDE, you can make use of the handles structure GUIDE creates to store data using the GUIDATA function.

SHAddToRecentDocs without a file?

I was toying with an IRC client, integrating it with the windows 7 app bar.
To get a "Frequent" or "Recent" items list one has to call SHAddToRecentDocs API.
I want to add recent IRC channels visited to the Windows 7 Jumplist for the IRC application.
Now, my problem is, IRC channels don't exist in the file system. And SHAddToRecentDocs seems to insist on getting some sort of file system object.
Ive tried to work around it by creating a IShellItem pointing to my application, and giving it a command line to launch the channel. The shell is rebelling however, and thus far has not visibly added any of my "recent document" attempts to the Jumplist.
Is there no way to do this without creating some kind of entirely unwanted filesystem object?
The code in the answer to question 1671793 goes part of the way. You want an IShellLink instead of an IShellItem. I tried that code bit by bit. Things wouldn't work before using the IPropertyStore to set the title. The IPersistFile code doesn't seem to be necessary.
All of that said, while I now have items appearing when I right-click on my app's taskbar icon, I don't yet have them appearing as a sub-menu of my app on the start menu (as word docs do, for example), so I'm not yet entirely satisfied. I think this is a result of the warning in the docs for SHAddToRecentDocs:
Executable (.exe) files are filtered from the recently used documents list in Windows XP and later versions. Although SHAddToRecentDocs will accept the path of an executable file, that file will not appear in the Recent Items list.
Here's my code as it stands. I'm jumping through some hoops as my development environment is using an older Windows SDK (so I have to create PKEY_Title for myself) and my app needs to support Win2k (so I don't want to bind to functions like InitPropVariantFromString which require newer Windows versions).
HRESULT hr;
IShellLink* link;
// Get a pointer to the IShellLink interface.
hr = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (LPVOID*)&link);
if (FAILED(hr))
return;
link->SetPath(path_to_app);
link->SetArguments(L"/some /args");
link->SetDescription(L"A description"); // Turns into tooltip
IPropertyStore* prop_store;
hr = link->QueryInterface(&prop_store);
if(SUCCEEDED(hr))
{
PROPVARIANT pv;
pv.vt=VT_LPWSTR;
pv.pwszVal=L"Name of item"; // Turns into actual item name
PROPERTYKEY PKEY_Title;
CLSIDFromString(L"{F29F85E0-4FF9-1068-AB91-08002B27B3D9}", &(PKEY_Title.fmtid));
PKEY_Title.pid=2;
// Set the title property.
hr = prop_store->SetValue(PKEY_Title, pv); // THIS is where the displayed title is actually set
// Save the changes we made to the property store
prop_store->Commit();
prop_store->Release();
}
SHARDAPPIDINFOLINK appinfo;
appinfo.pszAppID=L"Company.AppName"; // Previously registered using SetCurrentProcessExplicitAppUserModelID
appinfo.psl=link;
SHAddToRecentDocs(SHARD_APPIDINFOLINK, &appinfo);
link->Release();

Resources