How to populate a TreeView made in resource script - c++

I have to make a C++, VSPackage that contains a TreeView. I added one in the default dialog window of the project resource script (*.rc) from the toolbox window. The problem is that I don't know how to add items to it.
I looked on many websites but they have code for C# or other types of projects.
I found a project made by Song Ho Ahn and also the source code that can be found at the bottom of this website TreeView.
I tried to go to the TreeView properties window to see if there is something so I can add items to it and then finding a way to replace them, but nothing. I tried to use the code he written just to help me find a solution to my problem, but I couldn't find it. Maybe it's the "handler" and the "parent", which I don't know how to use.
void set(HWND parent, int id, bool visible=true)
{
this->parent = parent;
handle = GetDlgItem(parent, id);
if(!visible) disable();
}
I want to mention that I'm a beginner with VSPackage and that I didn't made a project this big before.
If somebody can explain to me what to do, send me on a path or even say that I'm stupid and the solution is a simple one, I will appreciate it very much.

In the snippet you've posted, you're using native WIN32 API. So you might look into the documentation of TVM_INSERTITEM message.
Here is a little snippet to add a single entry to a TreeView control (regardless if created by a resource script or a call of CreateWindow(..)):
TVITEM tvi;
TVINSERTSTRUCT tvins;
HTREEITEM hItem;
/* setup new item */
tvi.mask = TVIF_TEXT; // just text
tvi.pszText = "Hello TreeView!";
tvi.cchTextMax = 0; // ignored if creating the item
/* setup insertion structure of item */
tvins.hParent = TVI_ROOT; // insert item at root level
tvins.item = tvi; // item description setup above
tvins.hInsertAfter = NULL; // instert on top of the tree view
hItem = (HTREEITEM)SendMessage(GetDlgItem(hWnd, IDC_TREEVIEW), // update parameters of GetDlgItem(..) according to your code
TVM_INSERTITEM,
0,
(LPARAM)(LPTVINSERTSTRUCT)&tvins);
if (hItem == NULL)
{
/* something went wrong */
}

Related

MFC: Using ContextMenuManager to TrackPopupMenu causes CTreeView item to retain TVGN_DROPHILITE status from time to time

I have a weird issue with a CTreeView context menu. I was just calling pPopup->TrackPopupMenu() as is active in the code below. No problems, but doesn't automatically update status text and icons. So searching the Internet I found there is a ContextMenuManager for this in the MFC Feature Pack (I'm now using the BCGControlBar Pro which is what the feature pack was based on).
I tried using the ContextMenuManager in the code below (change the #if 1 to 0) and while it works, I find that sometimes (many times) afterwards the selected tree item will not show the highlight, it just flashes and goes back to the item that was right clicked on like TVGN_DROPHIILITE is still on. (I confirmed TVGN_DROPHILITE is what the right click uses to select the tree item via the debug print items on the OnNMRClick() function). Also if I enabled the treeCtrl.SelectDropTarget(NULL) it fixes the issue but I shouldn't have to do that?
I'd really like to use the ContextMenuManager but this issue is a show stopper. Does anyone know what is going on?
void CMyTreeView::OnNMRClick(NMHDR *pNMHDR, LRESULT *pResult)
{
CDebugPrint::DebugPrint(_T("NMRClick: In DropHighlightItem %p\n"), GetTreeCtrl().GetDropHilightItem());
// Send WM_CONTEXTMENU to self
SendMessage(WM_CONTEXTMENU, (WPARAM)m_hWnd, GetMessagePos());
CDebugPrint::DebugPrint(_T("NMRClick: Out DropHighlightItem %p\n"), GetTreeCtrl().GetDropHilightItem());
*pResult = 0;
}
void CMyTreeView::OnContextMenu(CWnd* pWnd, CPoint ptMousePos)
{
HTREEITEM htItem;
CTreeCtrl &treeCtrl=GetTreeCtrl();
//
// ...
//
// the popup is stored in a resource
CMenu menu;
menu.LoadMenu(IDR_TREE_CONTEXT_MENU);
CMenu* pPopup = menu.GetSubMenu(0);
#if 1
UINT id=pPopup->TrackPopupMenu(TPM_LEFTALIGN|TPM_RETURNCMD, ptMousePos.x, ptMousePos.y, this);
#else
CBCGPContextMenuManager *manager = theApp.GetContextMenuManager();
UINT id;
if (manager) {
id=manager->TrackPopupMenu(pPopup->GetSafeHmenu(), ptMousePos.x, ptMousePos.y, this);
// treeCtrl.SelectDropTarget(NULL); // fixes issue
}
else id=0;
#endif
//
// ...
//
}
The TVGN_DROPHILITE is a temporary selection, only valid for the duration of drag-and-drop operation. Why are you messing with that?
You should use TVGN_CARET, if anything.
However, the problem is that right-click doesn't select the clicked item. If you like that behavior (I do), select it yourself.
It is also strange that you // Send WM_CONTEXTMENU to self - the WM_CONTEXTMENU should be sent to you by the system, in response to right click.

How to set text below the QToolButton in QT not below the icon

I'm using QToolButton and I set the icon.
Now I want Text "below the QToolButton", "Not below the icon".
Is there any way to achieve this in C++,QT in Linux ?
I've found myself in the same position a while back ago while I was making an application for an embedded Linux system.
I haven't found a straight forward solution (I was searching for a way to achieve it with CSS).
What I ended up doing, was creating a new QWidget (using the designer). Then placing the button in it with a QLabel under it.
Then added a simple static function
static void wdgCustomButton::create(const QString iconPath, const QString text)
{
// create a new button here, create some modification functions for
// text, image and optionally QStyleSheets.
// Call those here (pass the arguments)
// Then return the button
// pseudo code, (not tested):
wdgCustomButton button = new wdgCustomButton( /* could pass a parent */ );
button->setIcon( iconPath ); // function simply calls the ui->button->setIcon
button->setText( text ); // function simply calls the ui->label->setText
return button;
}
And then add those new QWidgets to your pannel using code (maybe someone knows how to get it in the default toolbar, but I haven't searched for that myself yet since I never needed it).
this->menuButtons[menuBtnsCount] = wdgCustomButton::create( ":/Images/Warning.png", "Delete everything" );
this->menuButtons[menuBtnsCount]->setGeometry( QRect( /* size and position here */ ) );
this->menuButtons[menuBtnsCount]->show();
I hope this might give you an idea to fix it in an easy way!
Edit:
I'm sorry, I forgot to add something about the click event. The click event was mainly why I made a QWidget out of it!
I just used the connect function [I belive on the whole button like: connect(this->menuButtons[0], ...]

MSHTML: Callback on image insertion

Currently I am working on embedding a HTML editor into a C++ WinAPI application using the MSHTML component.
I got everything set up (activating editing mode, changing font face, etc.), but now I have to support inserting images. MSHTML already has support for it built in, but this support is - to my knowledge - not enough.
Somehow I need a way to intercept the insertion of images into the HTML-editor, since I have to create a list of images in the UI of our application. So, whenever the user uses the default-dialog of the MSHTML-component to insert an image or updates its source (e.g. from file://xyz.jpg to file://abc.jpg), I want my code to be notified.
I already looked at the conecpt of "Edit Designers", the implementation of IHTMLEditHost, or the DWebBrowserEvents2 interface. But nothing seems to do the trick.
Perhaps someone can give me a hint?
Okay,
it looks like you cannot explicitly subscribe for specific changes of the document. What you can do is to create a so-called "Change Sink".
Everytime you change the document, either by user input or programmatically, you can get a notification that "something" changed in your document. This can be done by implementing the IHTMLChangeSink interface and attaching it to the IMarkupContainer2 of the IHTMLDocument2.
Example code (not complete):
class CHTMLChangeSink : public IHTMLChangeSink
{
public:
// Implement IUnknown: QueryInterface, AddRef, Release
// Implement IHTMLChangeSink:
HRESULT STDMETHODCALLTYPE Notify()
{
// Notify() is called everytime the document changes
return S_OK;
}
};
CHTMLChangeSink * pChangeSink = new CHTMLChangeSink();
IHTMLDocument2 * pDoc; // lets suppose we already have it
IMarkupContainer2 * pMarkupContainer = nullptr;
if (pDoc->QueryInterface(IID_IMarkupContainer2, reinterpret_cast<void **>(&pMarkupContainer)) == S_OK) {
DWORD dwCookie = 1;
// registration is done here
pMarkupContainer->RegisterForDirtyRange(pChangeSink, &dwCookie);
}
Please be aware, that the document has to be loaded completely (register for DIID_DWebBrowserEvents2::DocumentComplete).
From now on, whenever a change in the document occurs, your Notify-method will be called and you can do further processing to find out what has changed (e.g. process the list of images in the document).
Have fun!

Dialog based New file in MFC

I want to pop-up a dialog for creating a new file in MFC
to collect detail information for a document like Photoshop. (e.g. width, height, depth .)
I found two answers from stackoverflow.
Configuring new document in MFC
MFC, File New with dialog to prompt for paramters and multiple Doc Types?
I want to try the formal one, but I cannot understand the suggestion:
just post a custom message/command to the main frame. Then add a handler that will react by the sequence pop up GUI/update doc/update views. That way, the main frame will be displayed before the GUI is popped up and your user will be happier.
Can anyone explain in detail?
Thanks in advance.
I'm not very sure about the answer you quoted, what I normally do is to pop up the dialog box to collect the new file information in the OnNewDocument() member function -- as the quoted question mentions, it's a bit ugly to put in a UI in the document class, but it works...
BOOL CMyDoc::OnNewDocument()
{ if (!CDocument::OnNewDocument()) // substitute CDocument with your document base class
return FALSE;
CFileNewInfo dlg(AfxGetApp()->GetMainWnd());
// ... set up dialog member variables
if (dlg.DoModal() != IDOK)
return FALSE;
// ... retrieve dialog member variables and update your document appropriately
return TRUE;
}

Using images in QListWidget, is this possible?

I am using QT to create a chat messenger client. To display the list of online users, I'm using a QListWidget, as created like this:
listWidget = new QListWidget(horizontalLayoutWidget);
listWidget->setObjectName("userList");
QSizePolicy sizePolicy1(QSizePolicy::Preferred, QSizePolicy::Expanding);
sizePolicy1.setHorizontalStretch(0);
sizePolicy1.setVerticalStretch(0);
sizePolicy1.setHeightForWidth(listWidget->sizePolicy().hasHeightForWidth());
listWidget->setSizePolicy(sizePolicy1);
listWidget->setMinimumSize(QSize(30, 0));
listWidget->setMaximumSize(QSize(150, 16777215));
listWidget->setBaseSize(QSize(100, 0));
listWidget->setContextMenuPolicy(Qt::CustomContextMenu);
Users are shown by constantly refreshing the list, like this: (Note: There are different channels, with different userlists, so refreshing it is the most efficient thing to do, as far as I know.)
void FMessenger::refreshUserlist()
{
if (currentPanel == 0)
return;
listWidget = this->findChild<QListWidget *>(QString("userList"));
listWidget->clear();
QList<FCharacter*> charList = currentPanel->charList();
QListWidgetItem* charitem = 0;
FCharacter* character;
foreach(character, charList)
{
charitem = new QListWidgetItem(character->name());
// charitem->setIcon(QIcon(":/Images/status.png"));
listWidget->addItem(charitem);
}
}
This has always worked perfectly. The line that I commented out is the one I have problems with: my current goal is to be able to display a user's online status with an image, which represents whether they are busy, away, available, etc. Using setIcon() does absolutely nothing though, apparently; the items still show up as they used to, without icons.
I'm aware that this is probably not the way this function needs to be used, but I have found little documentation about it online, and absolutely no useful examples of implementations. My question is, can anybody help me with fixing this problem?
This is how you may conduct your debugging:
Try the constructor that has both icon and text as arguments.
Try to use that icon in another context to ensure it is displayable (construct a QIcon with same argument and use it elsewhere, e.g. QLabel!).
Use icon() from the QListWidgetItem to receive back the icon and then look at that QIcon.
Create a new QListWidget, change nothing, and ordinarily add some stock items in your MainWidget's constructor. See if the icons show up there.