static void CustomizeTocInfoTip(LPNMTVGETINFOTIP nmit) { PageDestination *link = ((DocTocItem *)nmit->lParam)->GetLink(); ScopedMem<WCHAR> path(link ? link->GetDestValue() : nullptr); if (!path) return; CrashIf(!link); // /analyze claims that this could happen - it really can't CrashIf(link->GetDestType() != Dest_LaunchURL && link->GetDestType() != Dest_LaunchFile && link->GetDestType() != Dest_LaunchEmbedded); str::Str<WCHAR> infotip; RECT rcLine, rcLabel; HWND hTV = nmit->hdr.hwndFrom; // Display the item's full label, if it's overlong TreeView_GetItemRect(hTV, nmit->hItem, &rcLine, FALSE); TreeView_GetItemRect(hTV, nmit->hItem, &rcLabel, TRUE); if (rcLine.right + 2 < rcLabel.right) { WCHAR buf[INFOTIPSIZE+1] = { 0 }; // +1 just in case TVITEM item; item.hItem = nmit->hItem; item.mask = TVIF_TEXT; item.pszText = buf; item.cchTextMax = INFOTIPSIZE; TreeView_GetItem(hTV, &item); infotip.Append(item.pszText); infotip.Append(L"\r\n"); } if (Dest_LaunchEmbedded == link->GetDestType()) path.Set(str::Format(_TR("Attachment: %s"), path.Get())); infotip.Append(path); str::BufSet(nmit->pszText, nmit->cchTextMax, infotip.Get()); }
void CMsgTree::SetDefMsg(int iMode, int ID) { for (int i = 0; i < _countof(SettingsList); i++) { if (SettingsList[i].Status == iMode) { if (MsgTreePage.GetValue(SettingsList[i].DBSetting) != ID) { RECT rc; COptItem_TreeCtrl *TreeCtrl = GetTreeCtrl(); int OrderOld = TreeCtrl->IDToOrder(MsgTreePage.GetValue(SettingsList[i].DBSetting)); if (OrderOld >= 0 && TreeView_GetItemRect(hTreeView, TreeCtrl->Value[OrderOld].hItem, &rc, false)) InvalidateRect(hTreeView, &rc, true); // refresh icons of previous default tree item int OrderNew = TreeCtrl->IDToOrder(ID); if (OrderNew >= 0 && TreeView_GetItemRect(hTreeView, TreeCtrl->Value[OrderNew].hItem, &rc, false)) InvalidateRect(hTreeView, &rc, true); // refresh new default item icons MsgTreePage.SetValue(SettingsList[i].DBSetting, ID); NMMSGTREE nm = { 0 }; if (OrderOld >= 0) nm.ItemOld = &TreeCtrl->Value[OrderOld]; if (OrderNew >= 0) nm.ItemNew = &TreeCtrl->Value[OrderNew]; nm.hdr.code = MTN_DEFMSGCHANGED; nm.hdr.hwndFrom = hTreeView; nm.hdr.idFrom = GetDlgCtrlID(hTreeView); SendMessage(GetParent(hTreeView), WM_NOTIFY, 0, (LPARAM)&nm); } break; } } }
VOID TreeListUpdateTooltips( HWND hwndTreeList ) { HWND TreeControl = (HWND)GetWindowLongPtr(hwndTreeList, TL_TREECONTROL_SLOT), ToolTips = (HWND)GetWindowLongPtr(hwndTreeList, TL_TOOLTIPS_SLOT), Header = (HWND)GetWindowLongPtr(hwndTreeList, TL_HEADERCONTROL_SLOT); PTL_SUBITEMS subitems; HTREEITEM item = TreeView_GetRoot(TreeControl); RECT rc, subrc; TOOLINFO tool; ULONG i = 0, c; LONG cx; TVITEMEX itemex; RtlSecureZeroMemory(&rc, sizeof(rc)); Header_GetItemRect(Header, 0, &rc); cx = rc.right; c = (ULONG)SendMessage(ToolTips, TTM_GETTOOLCOUNT, 0, 0); RtlSecureZeroMemory(&tool, sizeof(tool)); tool.cbSize = sizeof(tool); while (SendMessage(ToolTips, TTM_ENUMTOOLS, i, (LPARAM)&tool) && (i < c)) { if (!TreeView_GetItemRect(TreeControl, (HTREEITEM)(tool.uId - tool.lParam), &rc, FALSE)) { SendMessage(ToolTips, TTM_DELTOOL, 0, (LPARAM)&tool); continue; } i++; } while (item) { if (TreeView_GetItemRect(TreeControl, item, &rc, TRUE)) { RtlSecureZeroMemory(&itemex, sizeof(itemex)); itemex.hItem = item; itemex.mask = TVIF_HANDLE | TVIF_PARAM; TreeView_GetItem(TreeControl, &itemex); if (rc.right > cx) rc.right = cx; AddTooltipItemSub(TreeControl, ToolTips, (UINT_PTR)item, 0, &rc); if (itemex.lParam) { subitems = (PTL_SUBITEMS)itemex.lParam; for (i = 0; i < subitems->Count; i++) { if (!Header_GetItemRect(Header, i + 1, &subrc)) break; subrc.top = rc.top; subrc.bottom = rc.bottom; AddTooltipItemSub(TreeControl, ToolTips, i + 1 + (UINT_PTR)item, i + 1, &subrc); } } } item = TreeView_GetNextVisible(TreeControl, item); } }
static VOID OnContext(PMAIN_WND_INFO Info, LPARAM lParam) { HTREEITEM hSelected; POINT pt; RECT rc; INT xPos = GET_X_LPARAM(lParam); INT yPos = GET_Y_LPARAM(lParam); hSelected = TreeView_GetSelection(Info->hTreeView); if (TreeView_GetItemRect(Info->hTreeView, hSelected, &rc, TRUE)) { if (GetCursorPos(&pt) && ScreenToClient(Info->hTreeView, &pt) && PtInRect(&rc, pt)) { TrackPopupMenuEx(Info->hShortcutMenu, TPM_RIGHTBUTTON, xPos, yPos, Info->hMainWnd, NULL); } } }
static BOOL ViewDlg_ToggleCheckItem(HWND hwndDlg, HTREEITEM hItem) { HWND hwndTreeView = GetDlgItem(hwndDlg, IDC_VIEW_TREEVIEW); // get the item TV_ITEM Item; INT i; ZeroMemory(&Item, sizeof(Item)); Item.mask = TVIF_HANDLE | TVIF_IMAGE | TVIF_PARAM; Item.hItem = hItem; if (!TreeView_GetItem(hwndTreeView, &Item)) return FALSE; // no such item VIEWTREE_ENTRY *pEntry = ViewTree_GetItem(Item.lParam); if (pEntry == NULL) return FALSE; // no such item if (pEntry->bGrayed) return FALSE; // disabled // toggle check mark Item.mask = TVIF_HANDLE | TVIF_IMAGE | TVIF_SELECTEDIMAGE; switch (pEntry->dwType) { case AETYPE_CHECKBOX: pEntry->bChecked = !pEntry->bChecked; break; case AETYPE_RADIO: // reset all the entries of the same parent for (i = 0; i < s_ViewTreeEntryCount; ++i) { VIEWTREE_ENTRY *pEntry2 = &s_ViewTreeEntries[i]; if (pEntry->dwParentID == pEntry2->dwParentID) { pEntry2->bChecked = FALSE; Item.hItem = pEntry2->hItem; INT iImage = ViewTree_GetImage(pEntry2); Item.iImage = Item.iSelectedImage = iImage; TreeView_SetItem(hwndTreeView, &Item); } } pEntry->bChecked = TRUE; break; default: return FALSE; // failure } Item.iImage = Item.iSelectedImage = ViewTree_GetImage(pEntry); Item.hItem = hItem; TreeView_SetItem(hwndTreeView, &Item); // redraw the item RECT rcItem; TreeView_GetItemRect(hwndTreeView, hItem, &rcItem, FALSE); InvalidateRect(hwndTreeView, &rcItem, TRUE); return TRUE; // success }
void CCList::SetExtraImage(HTREEITEM hItem, int iColumn, int iImage) // set iImage to CLC_EXTRAICON_EMPTY to reset image { _ASSERT(iColumn < MAXEXTRAICONS); GetItemData(hItem).ExtraIcons[iColumn] = iImage; RECT rc; if (TreeView_GetItemRect(hTreeView, hItem, &rc, false)) InvalidateRect(hTreeView, &rc, true); }
LRESULT TreeListOnCustomDraw( __in PTREELIST_OBJECT Object, __in LPNMHDR lp ) { LRESULT Status; LPNMTVCUSTOMDRAW lpcd = (LPNMTVCUSTOMDRAW)lp; Status = CDRF_DODEFAULT; switch (lpcd->nmcd.dwDrawStage) { case CDDS_PREPAINT: //SetViewportOrgEx(lpcd->nmcd.hdc, Object->ScrollOffset, 0, NULL); Status = CDRF_NOTIFYITEMDRAW; break; case CDDS_ITEMPREPAINT: // // Track item information for custom drawing after post painting stage // lpcd->clrText = Object->clrText; lpcd->clrTextBk = Object->clrBack; Object->ItemFocus = FALSE; if(lpcd->nmcd.uItemState & CDIS_FOCUS) { Object->ItemFocus = TRUE; } TreeView_GetItemRect(Object->hWndTree, (HTREEITEM)lpcd->nmcd.dwItemSpec, &Object->ItemRect, TRUE); Object->ItemRect.right = min(lpcd->nmcd.rc.right, Object->HeaderWidth); Status = CDRF_NOTIFYPOSTPAINT; break; case CDDS_ITEMPOSTPAINT: TreeListDrawItem(Object, lpcd->nmcd.hdc, (HTREEITEM)lpcd->nmcd.dwItemSpec, lpcd->nmcd.lItemlParam); Status = CDRF_SKIPDEFAULT; break; } return Status; }
/** * name: ShowItem * class: CPsTree * desc: displays on of the items in the treeview * param: iPageIndex - the index of the treeitem in the array. * needWidth - gives and takes the width, the treeview must have to show all items properly * return: TRUE if item was added successfully, FALSE otherwise **/ HTREEITEM CPsTree::ShowItem(const int iPageIndex, LPWORD needWidth) { TVINSERTSTRUCT tvii; CPsTreeItem *pti; // check parameters if (!_hWndTree || !IsIndexValid(iPageIndex) || !(pti = _pItems[iPageIndex]) || !pti->Name() || !pti->Label()) { MsgErr(GetParent(_hWndTree), LPGENT("Due to a parameter error, one of the treeitems can't be added!")); return NULL; } // item is visible at the moment if ((tvii.itemex.hItem = pti->Hti()) == NULL) { RECT rc; const int iParent = pti->Parent(); // init the rest of the treeitem tvii.hParent = IsIndexValid(iParent) ? ShowItem(iParent, needWidth) : NULL; tvii.hInsertAfter = (_dwFlags & PSTVF_SORTTREE) ? TVI_SORT : TVI_LAST; tvii.itemex.mask = TVIF_TEXT|TVIF_PARAM|TVIF_STATE; tvii.itemex.pszText = pti->Label(); tvii.itemex.state = pti->State() == DBTVIS_EXPANDED ? TVIS_EXPANDED : 0; tvii.itemex.stateMask = TVIS_EXPANDED; tvii.itemex.lParam = iPageIndex; // set images if ((tvii.itemex.iImage = tvii.itemex.iSelectedImage = pti->Image()) != -1) { tvii.itemex.mask |= TVIF_IMAGE|TVIF_SELECTEDIMAGE; } // insert item into tree if set visible if ((tvii.itemex.hItem = TreeView_InsertItem(_hWndTree, &tvii)) == NULL) { MsgErr(GetParent(_hWndTree), LPGENT("A fatal error occurred on adding a property sheet page!\nDialog creation aborted!")); return NULL; } pti->Hti(tvii.itemex.hItem); // calculate width of treeview if (needWidth && TreeView_GetItemRect(_hWndTree, pti->Hti(), &rc, TRUE) && rc.right > *needWidth) { *needWidth = (WORD)rc.right; } } return tvii.itemex.hItem; }
VOID TreeListAutoExpand( HWND hwndHeader, LPNMTREEVIEW nhdr ) { RECT irc; LONG cx = 0, xleft = 0; HDITEM hdi; HTREEITEM citem = TreeView_GetChild(nhdr->hdr.hwndFrom, nhdr->itemNew.hItem); RtlSecureZeroMemory(&irc, sizeof(irc)); TreeView_GetItemRect(nhdr->hdr.hwndFrom, citem, &irc, TRUE); xleft = irc.left; while (citem) { RtlSecureZeroMemory(&irc, sizeof(irc)); TreeView_GetItemRect(nhdr->hdr.hwndFrom, citem, &irc, TRUE); if (irc.left < xleft) break; if (irc.right > cx) cx = irc.right; citem = TreeView_GetNextVisible(nhdr->hdr.hwndFrom, citem); } RtlSecureZeroMemory(&hdi, sizeof(hdi)); hdi.mask = HDI_WIDTH; Header_GetItem(hwndHeader, 0, &hdi); if (hdi.cxy < cx + 8) hdi.cxy = cx + 8; Header_SetItem(hwndHeader, 0, &hdi); }
bool GetNodeRect(_Ty Key, PRECT pRc) { bool r = false; HTREEITEM hItem = KeyToHandle(Key); if (NULL != hItem) { if (TRUE == TreeView_GetItemRect(m_hWnd, hItem, pRc, FALSE)) { r = true; } } return r; }
/** * name: OnIconsChanged * class: CPsTreeItem * desc: Handles reloading icons if changed by icolib * params: none * return: nothing **/ void CPsTreeItem::OnIconsChanged(CPsTree *pTree) { HICON hIcon; RECT rc; // update tree item icons if (pTree->ImageList() && (hIcon = IcoLib_GetIcon(IconKey())) != NULL) { _iImage = (_iImage > 0) ? ImageList_ReplaceIcon(pTree->ImageList(), _iImage, hIcon) : ImageList_AddIcon(pTree->ImageList(), hIcon); if (_hItem && TreeView_GetItemRect(pTree->Window(), _hItem, &rc, 0)) InvalidateRect(pTree->Window(), &rc, TRUE); } // update pages icons OnPageIconsChanged(); }
LRESULT CDeviceView::OnContextMenu( _In_ LPARAM lParam ) { HTREEITEM hSelected = TreeView_GetSelection(m_hTreeView); RECT rc; if (TreeView_GetItemRect(m_hTreeView, hSelected, &rc, TRUE)) { POINT pt; if (GetCursorPos(&pt) && ScreenToClient(m_hTreeView, &pt) && PtInRect(&rc, pt)) { CNode *Node = GetSelectedNode(); if (Node) { // Create the context menu HMENU hContextMenu = CreatePopupMenu(); // Add the actions for this node BuildActionMenuForNode(hContextMenu, Node, false); INT xPos = GET_X_LPARAM(lParam); INT yPos = GET_Y_LPARAM(lParam); // Display the menu TrackPopupMenuEx(hContextMenu, TPM_RIGHTBUTTON, xPos, yPos, m_hMainWnd, NULL); DestroyMenu(hContextMenu); } } } return 0; }
HTREEITEM CCList::HitTest(LPPOINT pt, PDWORD hitFlags) // pt is relative to control; returns hItem or NULL { TVHITTESTINFO hti; hti.pt = *pt; TreeView_HitTest(hTreeView, &hti); *hitFlags = 0; if (hti.flags & TVHT_ABOVE) *hitFlags |= MCLCHT_ABOVE; if (hti.flags & TVHT_BELOW) *hitFlags |= MCLCHT_BELOW; if (hti.flags & TVHT_TOLEFT) *hitFlags |= MCLCHT_TOLEFT; if (hti.flags & TVHT_TORIGHT) *hitFlags |= MCLCHT_TORIGHT; if (hti.flags & TVHT_NOWHERE) *hitFlags |= MCLCHT_NOWHERE; if (hti.flags & TVHT_ONITEMINDENT) *hitFlags |= MCLCHT_ONITEMINDENT; if (hti.flags & (TVHT_ONITEMICON | TVHT_ONITEMSTATEICON)) *hitFlags |= MCLCHT_ONITEMICON; if (hti.flags & TVHT_ONITEMLABEL) *hitFlags |= MCLCHT_ONITEMLABEL; if (hti.flags & TVHT_ONITEMRIGHT) *hitFlags |= MCLCHT_ONITEMRIGHT; if (hti.flags & (TVHT_ONITEMINDENT | TVHT_ONITEM | TVHT_ONITEMRIGHT)) { // extraicon tests RECT rc; if (TreeView_GetItemRect(hTreeView, hti.hItem, &rc, false)) { int nIndex = (rc.right - pt->x - 1) / EXTRAICON_XSTEP; if (nIndex >= 0 && nIndex < MAXEXTRAICONS && GetItemData(hti.hItem).ExtraIcons[nIndex] != CLC_EXTRAICON_EMPTY) *hitFlags |= MCLCHT_ONITEMEXTRA | (nIndex << 24); } } return hti.hItem; }
//---------------------------------------------------// // TreeView_StartProc //---------------------------------------------------// BOOL TreeView_StartProc(HWND hWndActive) { GetmHpVarStruct()->hWndCurCtrl=NULL; /*if(*GetmHpVarStruct()->CourantTask->GetmHpCtrlName()!=0) { if(mHpPak_IsDotNetHwnd(hWndActive)) { int iState=0,iStyle=0; GetmHpVarStruct()->hWndCurCtrl=mHpPak_GetDotNetCtrlHandle(hWndActive,GetmHpVarStruct()->CourantTask->GetmHpCtrlName(),iStyle,iState); } }*/ if(!GetmHpVarStruct()->hWndCurCtrl) GetmHpVarStruct()->hWndCurCtrl=GetCtrlWnd(hWndActive,GetmHpVarStruct()->CourantTask->GetmHpCtrlID()); if(!IsCtrlReady(hWndActive,GetmHpVarStruct()->hWndCurCtrl)) return FALSE; RECT CtrlRct; GetWindowRect(GetmHpVarStruct()->hWndCurCtrl,&CtrlRct); GetmHpVarStruct()->SelItemListe->EmptyGroupListe(); GetTVitemSelList(GetmHpVarStruct()->hWndCurCtrl,TreeView_GetRoot(GetmHpVarStruct()->hWndCurCtrl),0); GetmHpVarStruct()->SelItemListe->ReplaceCurrent(); hCurSelItm=GetNexthTreeItemToSel(GetmHpVarStruct()->hWndCurCtrl,TreeView_GetRoot(GetmHpVarStruct()->hWndCurCtrl)); if(hCurSelItm==NULL) { bFindItm=FALSE; GetmHpVarStruct()->CourantTask->SetmHpStep(13); GetmHpVarStruct()->YnextPos=(int)(((CtrlRct.bottom-CtrlRct.top)/2)+CtrlRct.top); GetmHpVarStruct()->XnextPos=(int)(((CtrlRct.right-CtrlRct.left)/2)+CtrlRct.left); } else { bFindItm=TRUE; if(GetmHpVarStruct()->imHpMode==1) TreeView_EnsureVisible(GetmHpVarStruct()->hWndCurCtrl,hCurSelItm); RECT itmRct; TreeView_GetItemRect(GetmHpVarStruct()->hWndCurCtrl,hCurSelItm,&itmRct,TRUE); ListTreeStatusPos(hWndActive,itmRct); if(!GetmHpVarStruct()->AscensSens) { GetmHpVarStruct()->YnextPos=(int)(CtrlRct.top+((itmRct.bottom-itmRct.top)/2)+itmRct.top); GetmHpVarStruct()->XnextPos=(int)(CtrlRct.left+((itmRct.right-itmRct.left)/2)+itmRct.left); // Click | DoubleClick if(!GetmHpVarStruct()->SelItemListe->IsNextIndexExist()) GetmHpVarStruct()->CourantTask->SetmHpStep(10); } else // Not visible { GetmHpVarStruct()->CourantTask->SetmHpStep(10); MoveOnScrollBar(GetmHpVarStruct()->hWndCurCtrl,CtrlRct); } } return TRUE; }
/** * name: BeginLabelEdit * class: CPsTree * desc: begins the labeledit mode * param: hItem - handle of the treeitm whose label to edit * return: 0 **/ int CPsTree::BeginLabelEdit(HTREEITEM hItem) { CPsTreeItem* pti; // tree is readonly if (db_get_b(NULL, MODNAME, SET_PROPSHEET_READONLYLABEL, 0)) return 0; // get item text if (!hItem && !(hItem = TreeView_GetSelection(_hWndTree))) return 0; if (pti = FindItemByHandle(hItem)) { RECT rc, rcTree; // create the edit control GetClientRect(_hWndTree, &rcTree); TreeView_GetItemRect(_hWndTree, hItem, &rc, TRUE); _hLabelEdit = CreateWindowEx(WS_EX_NOPARENTNOTIFY|WS_EX_CLIENTEDGE, _T( "EDIT" ), pti->Label(), WS_VISIBLE|ES_AUTOHSCROLL|WS_CHILD, rc.left, rc.top, rcTree.right - rc.left, rc.bottom - rc.top, _hWndTree, NULL, ghInst, NULL ); if (_hLabelEdit) { _hDragItem = hItem; SetUserData(_hLabelEdit, this); mir_subclassWindow(_hLabelEdit, TPropsheetTree_LabelEditProc); SendMessage(_hLabelEdit, WM_SETFONT, (WPARAM)GetStockObject(DEFAULT_GUI_FONT), 0 ); Edit_SetSel(_hLabelEdit, 0, -1); Edit_LimitText(_hLabelEdit, MAX_TINAME); SetFocus(_hLabelEdit); return 0; } } return 1; }
VOID TreeListGetTreeRectMostRight( __in PTREELIST_OBJECT Object, __out PLONG MostRight ) { HTREEITEM hTreeItem; HWND hWndTree; RECT Rect; hWndTree = Object->hWndTree; hTreeItem = TreeView_GetFirstVisible(hWndTree); *MostRight = 0; while (hTreeItem != NULL) { TreeView_GetItemRect(hWndTree, hTreeItem, &Rect, TRUE); *MostRight = max(Rect.right, *MostRight); hTreeItem = TreeView_GetNextVisible(hWndTree, hTreeItem); } }
/* static DrawTheImage(HIMAGELIST himl) { HDC hDC; hDC=GetDC(NULL); ImageList_Draw(himl,0,hDC,0,0,ILD_NORMAL); ImageList_Draw(himl,1,hDC,20,0,ILD_NORMAL); ReleaseDC(NULL,hDC); } */ static void Main_OnBeginDrag(HWND hwndTV, LPNMTREEVIEW lpnmtv) { HIMAGELIST himl; // handle to image list RECT rcItem; // bounding rectangle of item // Tell the tree view control to create an image to use // for dragging. hDragWnd=hwndTV; himl = TreeView_CreateDragImage(hwndTV, lpnmtv->itemNew.hItem); // Real OK hDragItem=lpnmtv->itemNew.hItem; // Get the bounding rectangle of the item being dragged. TreeView_GetItemRect(hwndTV, lpnmtv->itemNew.hItem, &rcItem, TRUE); // Get the heading level and the amount that the child items are // indented. //dwLevel = 1;//lpnmtv->itemNew.lParam; //dwIndent = (DWORD) SendMessage(hwndTV, TVM_GETINDENT, 0, 0); //ImageList_SetDragCursorImage(himl,0,0,0); // Start the drag operation. //ShowCursor(FALSE); ImageList_BeginDrag(himl, 0, 0,0); // ImageList_DragEnter(NULL,0,0); ImageList_DragEnter(hDragWnd,0,0); //ImageList_DragShowNolock(TRUE); // Hide the mouse cursor, and direct mouse input to the // parent window. //DrawTheImage(himl); SetCapture(GetParent(hwndTV)); fDragging = TRUE; return; }
static void OnFavTreeContextMenu(WindowInfo* win, PointI pt) { TVITEM item; if (pt.x != -1 || pt.y != -1) { TVHITTESTINFO ht = {0}; ht.pt.x = pt.x; ht.pt.y = pt.y; MapWindowPoints(HWND_DESKTOP, win->hwndFavTree, &ht.pt, 1); TreeView_HitTest(win->hwndFavTree, &ht); if ((ht.flags & TVHT_ONITEM) == 0) return; // only display menu if over a node in tree TreeView_SelectItem(win->hwndFavTree, ht.hItem); item.hItem = ht.hItem; } else { item.hItem = TreeView_GetSelection(win->hwndFavTree); if (!item.hItem) { return; } RECT rcItem; if (TreeView_GetItemRect(win->hwndFavTree, item.hItem, &rcItem, TRUE)) { MapWindowPoints(win->hwndFavTree, HWND_DESKTOP, (POINT*)&rcItem, 2); pt.x = rcItem.left; pt.y = rcItem.bottom; } else { WindowRect rc(win->hwndFavTree); pt = rc.TL(); } } item.mask = TVIF_PARAM; TreeView_GetItem(win->hwndFavTree, &item); Favorite* toDelete = (Favorite*)item.lParam; HMENU popup = BuildMenuFromMenuDef(menuDefFavContext, dimof(menuDefFavContext), CreatePopupMenu()); INT cmd = TrackPopupMenu(popup, TPM_RETURNCMD | TPM_RIGHTBUTTON, pt.x, pt.y, 0, win->hwndFavTree, nullptr); DestroyMenu(popup); if (IDM_FAV_DEL == cmd) { RememberFavTreeExpansionStateForAllWindows(); if (toDelete) { DisplayState* f = gFavorites.GetByFavorite(toDelete); gFavorites.Remove(f->filePath, toDelete->pageNo); } else { // toDelete == nullptr => this is a parent node signifying all bookmarks in a file item.hItem = TreeView_GetChild(win->hwndFavTree, item.hItem); item.mask = TVIF_PARAM; TreeView_GetItem(win->hwndFavTree, &item); toDelete = (Favorite*)item.lParam; DisplayState* f = gFavorites.GetByFavorite(toDelete); gFavorites.RemoveAllForFile(f->filePath); } UpdateFavoritesTreeForAllWindows(); prefs::Save(); // TODO: it would be nice to have a system for undo-ing things, like in Gmail, // so that we can do destructive operations without asking for permission via // invasive model dialog boxes but also allow reverting them if were done // by mistake } }
static void TreeCtrlOnPaint(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { PAINTSTRUCT ps; HDC hDC; RECT rcClip, rcClient; HDC memDC; HBITMAP bitmap; HBITMAP hOldBitmap; HBITMAP hBackground = GetBackgroundBitmap(); MYBITMAPINFO *bmDesc = GetBackgroundInfo(); hDC = BeginPaint(hWnd, &ps); GetClipBox(hDC, &rcClip); GetClientRect(hWnd, &rcClient); // Create a compatible memory DC memDC = CreateCompatibleDC(hDC); // Select a compatible bitmap into the memory DC bitmap = CreateCompatibleBitmap(hDC, rcClient.right - rcClient.left, rcClient.bottom - rcClient.top); hOldBitmap = SelectObject(memDC, bitmap); // First let the control do its default drawing. CallWindowProc(g_lpTreeWndProc, hWnd, uMsg, (WPARAM)memDC, 0); // Draw bitmap in the background { HPALETTE hPAL; HDC maskDC; HBITMAP maskBitmap; HDC tempDC; HDC imageDC; HBITMAP bmpImage; HBITMAP hOldBmpImage; HBITMAP hOldMaskBitmap; HBITMAP hOldHBitmap; int i, j; RECT rcRoot; // Now create a mask maskDC = CreateCompatibleDC(hDC); // Create monochrome bitmap for the mask maskBitmap = CreateBitmap(rcClient.right - rcClient.left, rcClient.bottom - rcClient.top, 1, 1, NULL); hOldMaskBitmap = SelectObject(maskDC, maskBitmap); SetBkColor(memDC, GetSysColor(COLOR_WINDOW)); // Create the mask from the memory DC BitBlt(maskDC, 0, 0, rcClient.right - rcClient.left, rcClient.bottom - rcClient.top, memDC, rcClient.left, rcClient.top, SRCCOPY); tempDC = CreateCompatibleDC(hDC); hOldHBitmap = SelectObject(tempDC, hBackground); imageDC = CreateCompatibleDC(hDC); bmpImage = CreateCompatibleBitmap(hDC, rcClient.right - rcClient.left, rcClient.bottom - rcClient.top); hOldBmpImage = SelectObject(imageDC, bmpImage); hPAL = GetBackgroundPalette(); if (hPAL == NULL) hPAL = CreateHalftonePalette(hDC); if (GetDeviceCaps(hDC, RASTERCAPS) & RC_PALETTE && hPAL != NULL) { SelectPalette(hDC, hPAL, FALSE); RealizePalette(hDC); SelectPalette(imageDC, hPAL, FALSE); } // Get x and y offset TreeView_GetItemRect(hWnd, TreeView_GetRoot(hWnd), &rcRoot, FALSE); rcRoot.left = -GetScrollPos(hWnd, SB_HORZ); // Draw bitmap in tiled manner to imageDC for (i = rcRoot.left; i < rcClient.right; i += bmDesc->bmWidth) for (j = rcRoot.top; j < rcClient.bottom; j += bmDesc->bmHeight) BitBlt(imageDC, i, j, bmDesc->bmWidth, bmDesc->bmHeight, tempDC, 0, 0, SRCCOPY); // Set the background in memDC to black. Using SRCPAINT with black and any other // color results in the other color, thus making black the transparent color SetBkColor(memDC, RGB(0,0,0)); SetTextColor(memDC, RGB(255,255,255)); BitBlt(memDC, rcClip.left, rcClip.top, rcClip.right - rcClip.left, rcClip.bottom - rcClip.top, maskDC, rcClip.left, rcClip.top, SRCAND); // Set the foreground to black. See comment above. SetBkColor(imageDC, RGB(255,255,255)); SetTextColor(imageDC, RGB(0,0,0)); BitBlt(imageDC, rcClip.left, rcClip.top, rcClip.right - rcClip.left, rcClip.bottom - rcClip.top, maskDC, rcClip.left, rcClip.top, SRCAND); // Combine the foreground with the background BitBlt(imageDC, rcClip.left, rcClip.top, rcClip.right - rcClip.left, rcClip.bottom - rcClip.top, memDC, rcClip.left, rcClip.top, SRCPAINT); // Draw the final image to the screen BitBlt(hDC, rcClip.left, rcClip.top, rcClip.right - rcClip.left, rcClip.bottom - rcClip.top, imageDC, rcClip.left, rcClip.top, SRCCOPY); SelectObject(maskDC, hOldMaskBitmap); SelectObject(tempDC, hOldHBitmap); SelectObject(imageDC, hOldBmpImage); DeleteDC(maskDC); DeleteDC(imageDC); DeleteDC(tempDC); DeleteObject(bmpImage); DeleteObject(maskBitmap); if (GetBackgroundPalette() == NULL) { DeleteObject(hPAL); hPAL = 0; } } SelectObject(memDC, hOldBitmap); DeleteObject(bitmap); DeleteDC(memDC); EndPaint(hWnd, &ps); ReleaseDC(hWnd, hDC); }
LRESULT CALLBACK WndProc( HWND hWnd, // window handle UINT message, // type of message WPARAM uParam, // additional information LPARAM lParam // additional information ) { FARPROC lpProcAbout; // pointer to the "About" function int wmId, wmEvent; //****************** NEW CODE START ********* #define ptrNMHDR ((LPNMHDR)lParam) #define ptrNM_TREEVIEW ((NM_TREEVIEW *)lParam) #define ptrTV_DISPINFO ((TV_DISPINFO *)lParam) RECT rcItem; static HIMAGELIST hDragImage; static BOOL bDragging; static HTREEITEM hDragItem; switch (message) { case WM_NOTIFY: // This is a new Chicago message for control // notifications switch (ptrNMHDR->code) { case TVN_BEGINDRAG: // Sent by TreeView when user // wants to drag an item. // Only allow drag & drop for the actual coaster // items. The "itemNew" field of the NM_TREEVIEW // structure contains the attribytes of the item // we are going to drag. Therefore, since we are // using the lParam field to store an ITEM_TYPE_* // value, we check that field. if ( ITEM_TYPE_COASTER_NAME == ptrNM_TREEVIEW->itemNew.lParam) { // The hDragImage variable is declared static, // so the code in WM_LBUTTONUP can delete it when // the user stops dragging. Here we create a // drag image to use for the ImageList_StartDrag // API. hDragImage = TreeView_CreateDragImage ( ptrNMHDR->hwndFrom, ptrNM_TREEVIEW->itemNew.hItem ); // Get the location of the item rectangle's text. TreeView_GetItemRect ( ptrNMHDR->hwndFrom, // Handle of TreeView ptrNM_TREEVIEW->itemNew.hItem, // Item in TreeView &rcItem, // RECT to store result TRUE // Rect of label text only ); // Cache away the handle of the item to drag into a // staticly declared variable, so the code in // WM_LBUTTONUP can know what the user is dragging. hDragItem = ptrNM_TREEVIEW->itemNew.hItem; // Start the drag ala ImageList ImageList_BeginDrag(hDragImage, 0, ptrNM_TREEVIEW->ptDrag.x - rcItem.left, // Offset hotspot ptrNM_TREEVIEW->ptDrag.y - rcItem.top); ImageList_DragEnter(ptrNMHDR->hwndFrom, ptrNM_TREEVIEW->ptDrag.x, // Coords of image to drag ptrNM_TREEVIEW->ptDrag.y); // Capture the mousey to this window ShowCursor ( FALSE ); SetCapture ( hWnd ); // Set a staticly declared drag flag so the WM_MOUSEMOVE // and WM_LBUTTONUP messages know to take action. bDragging = TRUE; } return 0L; // Return value is irrelevant case TVN_GETDISPINFO: // Sent by TreeView just before it paints // an item declared with callback values. // Our "state" items have the I_IMAGECALLBACK value // used for the iImage and iSelectedImage fields. This // TVN_GETDISPINFO code will be called whenever the // item is about to be drawn. It is out responsibility // to add code to fill in the images. The code below // uses a different image depending on if the item is // expanded or collapsed. That attribute is in the // state field of the item passed in the TV_DISPINFO // structure. // Our lParam is where we store what state the item // represents. Therefore, we will switch on that so // we can indicate the correct image to use. if ( ptrTV_DISPINFO->item.state & TVIS_EXPANDED ) { switch (ptrTV_DISPINFO->item.lParam) { case ITEM_TYPE_STATE_CA: ptrTV_DISPINFO->item.iImage = ptrTV_DISPINFO->item.iSelectedImage = iImageCA_OPEN; break; case ITEM_TYPE_STATE_NY: ptrTV_DISPINFO->item.iImage = ptrTV_DISPINFO->item.iSelectedImage = iImageNY_OPEN; break; case ITEM_TYPE_STATE_OH: ptrTV_DISPINFO->item.iImage = ptrTV_DISPINFO->item.iSelectedImage = iImageOH_OPEN; break; } } else // Collapsed item { switch (ptrTV_DISPINFO->item.lParam) { case ITEM_TYPE_STATE_CA: ptrTV_DISPINFO->item.iImage = ptrTV_DISPINFO->item.iSelectedImage = iImageCA; break; case ITEM_TYPE_STATE_NY: ptrTV_DISPINFO->item.iImage = ptrTV_DISPINFO->item.iSelectedImage = iImageNY; break; case ITEM_TYPE_STATE_OH: ptrTV_DISPINFO->item.iImage = ptrTV_DISPINFO->item.iSelectedImage = iImageOH; break; } } return TRUE; case TVN_BEGINLABELEDIT: // Sent by TreeView when user single // clicks on an item in a TreeView // that has the TVS_EDITLABELS style // bit set. // Only allow label editing for the coaster names if (ITEM_TYPE_COASTER_NAME == ptrTV_DISPINFO->item.lParam) return 0; // Return 0 to OK edit else return 1; // Return non-zero to disallow edit break; case TVN_ENDLABELEDIT: // Sent by TreeView when user presses // the ENTER key or ESC key, to end // an in-place edit session. If the user // pressed the ESC key, the pszText // field of the item in the TV_DISPINFO // field is NULL. // if user pressed ENTER to accept edits if ( ptrTV_DISPINFO->item.pszText) { // Set the "change mask" to indicate that the only attribute // we wish to change is the text field. The TV_DISPINFO // structure has already been filled out with the new // text the user typed in, we just need to pass that on // to the TreeView control. This is our chance to evaluate // the contents of this field and change it. ptrTV_DISPINFO->item.mask = TVIF_TEXT; TreeView_SetItem ( ptrNMHDR->hwndFrom, // Handle of TreeView &(ptrTV_DISPINFO->item) // TV_ITEM structure w/changes ); } break; } return (DefWindowProc(hWnd, message, uParam, lParam)); case WM_MOUSEMOVE: // Since the mouse capture is set to this // window while we do our drag & drop, // we check for the drag flag and process // the WM_MOUSEMOVE message. if (bDragging) { HTREEITEM hTarget; // Item under mouse TV_HITTESTINFO tvht; // Used for hit testing // Do standard drag drop movement ImageList_DragMove ( LOWORD (lParam), HIWORD (lParam)); // Fill out hit test struct with mouse pos tvht.pt.x = LOWORD (lParam); tvht.pt.y = HIWORD (lParam); // Check to see if an item lives under the mouse if ( hTarget = TreeView_HitTest ( hWndTreeView, // This is the global variable &tvht // TV_HITTESTINFO struct ) ) { TV_ITEM tvi; // Temporary Item tvi.mask = TVIF_PARAM; // We want to fetch the // lParam field. tvi.hItem = hTarget; // Set the handle of the // item to fetch. TreeView_GetItem ( hWndTreeView, &tvi ); // Fetch, spot! // Check to see if the lParam is a valid item to drop // onto (in this case, another roller coaster, such as // the Coney Island Cyclone). Skip this operation if // the item is already selected (to avoid flicker) if ( ITEM_TYPE_COASTER_NAME == tvi.lParam ) { if ( hTarget != TreeView_GetDropHilight (hWndTreeView)) { // Hide the drag image ImageList_DragShowNolock ( FALSE ); //DragShow to DragShowNoLock lithangw // Select the item TreeView_SelectDropTarget ( hWndTreeView, hTarget ); // Show the drag image ImageList_DragShowNolock ( TRUE ); //DragShow to DragShowNoLock lithangw } return 0L; } } // If we made it here, then the user has either // dragged the mouse over an invalid item, or no item. // Hide any current drop target, this is a no-no drop ImageList_DragShowNolock ( FALSE ); //screen update problem tokuroy TreeView_SelectDropTarget ( hWndTreeView, NULL ); ImageList_DragShowNolock ( TRUE ); //screen update problem tokuroy } break; case WM_LBUTTONUP: // Since the mouse capture is set to this // window while we do our drag & drop, // we check for the drag flag and process // the WM_LBUTTONUP message. if (bDragging) { HTREEITEM hTarget; // Item under mouse TV_ITEM tvi; // Temporary Item TV_INSERTSTRUCT tvIns; // Insert struct char szBuffer[256]; // Item text buffer // End the drag ImageList_EndDrag(); // Bring back the cursor ShowCursor ( TRUE ); // Release the mouse capture ReleaseCapture(); // Clear the drag flag bDragging = FALSE; // Clean up the image list object ImageList_Destroy ( hDragImage ); hDragImage = NULL; // First, check to see if there is a valid drop point. // The cheezy way to do this is to check for a highlighted // drop target, since the logic to validate drop points // is in the WM_MOUSEMOVE. Duping that code here would // be a headache. if ( hTarget = TreeView_GetDropHilight (hWndTreeView)) { // If we made it here, then we need to move the item. // First, we will fetch it, specifying the attributes // we need to copy. tvi.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_PARAM; tvi.hItem = hDragItem; tvi.pszText = szBuffer; tvi.cchTextMax = sizeof(szBuffer); TreeView_GetItem ( hWndTreeView, &tvi ); // Now, figure the new place to put it by filling out // the TV_INSERTSTRUCT structure, to use the drop target // as the sibling to insert after, and using the drop // target's parent as the parent to insert this one // after as well. tvIns.hParent = TreeView_GetParent ( hWndTreeView, hTarget ); tvIns.hInsertAfter = hTarget; tvIns.item = tvi; // Delete the old item TreeView_DeleteItem ( hWndTreeView, hDragItem ); // And add the new item (if your app tracks the handles of // the items, you want to use the return value // of this function to update your data structure that // tracks the handles. TreeView_InsertItem ( hWndTreeView, &tvIns ); } // Clear any drop highlights on the TreeView TreeView_SelectDropTarget ( hWndTreeView, NULL ); } break; case WM_SIZE: if ( hWndTreeView ) // Standard code to keep the TreeView // sized up with the main window { SetWindowPos ( hWndTreeView, NULL, 0, 0, LOWORD (lParam), HIWORD (lParam), SWP_NOZORDER ); } break; //****************** NEW CODE END ********* case WM_COMMAND: // message: command from application menu // Message packing of uParam and lParam have changed for Win32, // let us handle the differences in a conditional compilation: #if defined (_WIN32) wmId = LOWORD(uParam); wmEvent = HIWORD(uParam); #else wmId = uParam; wmEvent = HIWORD(lParam); #endif switch (wmId) { case IDM_ABOUT: lpProcAbout = MakeProcInstance((FARPROC)About, hInst); DialogBox(hInst, // current instance "AboutBox", // dlg resource to use hWnd, // parent handle (DLGPROC)lpProcAbout); // About() instance address FreeProcInstance(lpProcAbout); break; case IDM_EXIT: DestroyWindow (hWnd); break; case IDM_HELPCONTENTS: if (!WinHelp (hWnd, "TREEVIEW.HLP", HELP_KEY,(DWORD)(LPSTR)"CONTENTS")) { MessageBox (GetFocus(), "Unable to activate help", szAppName, MB_SYSTEMMODAL|MB_OK|MB_ICONHAND); } break; case IDM_HELPSEARCH: if (!WinHelp(hWnd, "TREEVIEW.HLP", HELP_PARTIALKEY, (DWORD)(LPSTR)"")) { MessageBox (GetFocus(), "Unable to activate help", szAppName, MB_SYSTEMMODAL|MB_OK|MB_ICONHAND); } break; case IDM_HELPHELP: if(!WinHelp(hWnd, (LPSTR)NULL, HELP_HELPONHELP, 0)) { MessageBox (GetFocus(), "Unable to activate help", szAppName, MB_SYSTEMMODAL|MB_OK|MB_ICONHAND); } break; // Here are all the other possible menu options, // all of these are currently disabled: case IDM_NEW: case IDM_OPEN: case IDM_SAVE: case IDM_SAVEAS: case IDM_UNDO: case IDM_CUT: case IDM_COPY: case IDM_PASTE: case IDM_LINK: case IDM_LINKS: default: return (DefWindowProc(hWnd, message, uParam, lParam)); } break; case WM_DESTROY: // message: window being destroyed PostQuitMessage(0); break; default: // Passes it on if unproccessed return (DefWindowProc(hWnd, message, uParam, lParam)); } return (0); }
LRESULT CALLBACK ParentSubclassProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) { CCList *dat = CWndUserData(hWnd).GetCList(); switch (Msg) { case WM_NOTIFY: { LPNMHDR pnmh = (LPNMHDR)lParam; if (pnmh->hwndFrom == dat->hTreeView) { switch (pnmh->code) { case TVN_ITEMEXPANDED: // just set an appropriate group image { LPNMTREEVIEW pnmtv = (LPNMTREEVIEW)lParam; TVITEM tvItem; tvItem.hItem = pnmtv->itemNew.hItem; tvItem.mask = TVIF_HANDLE | TVIF_IMAGE | TVIF_SELECTEDIMAGE; tvItem.iImage = tvItem.iSelectedImage = (pnmtv->itemNew.state & TVIS_EXPANDED) ? IMAGE_GROUPOPEN : IMAGE_GROUPSHUT; TreeView_SetItem(dat->hTreeView, &tvItem); } break; case TVN_SELCHANGED: { LPNMTREEVIEW pnmtv = (LPNMTREEVIEW)lParam; TREEITEMARRAY OldSelection = dat->SelectedItems; for (int i = 0; i < dat->SelectedItems.GetSize(); i++) { if (dat->SelectedItems[i] != pnmtv->itemNew.hItem) { TreeView_SetItemState(dat->hTreeView, dat->SelectedItems[i], 0, TVIS_SELECTED); } } dat->SelectedItems.RemoveAll(); if (pnmtv->itemNew.hItem) { dat->SelectedItems.AddElem(pnmtv->itemNew.hItem); dat->SelectGroups(pnmtv->itemNew.hItem, true); } NMCLIST nm; nm.hdr.code = MCLN_SELCHANGED; nm.hdr.hwndFrom = dat->hTreeView; nm.hdr.idFrom = GetDlgCtrlID(dat->hTreeView); nm.OldSelection = &OldSelection; nm.NewSelection = &dat->SelectedItems; SendMessage(hWnd, WM_NOTIFY, 0, (LPARAM)&nm); } break; case TVN_DELETEITEM: if (dat->Items.GetSize()) { // if Items size = 0, then this TVN_DELETEITEM came after WM_DESTROY, so there is no need to do anything LPNMTREEVIEW pnmtv = (LPNMTREEVIEW)lParam; TREEITEMARRAY OldSelection = dat->SelectedItems; int Index = dat->SelectedItems.Find(pnmtv->itemOld.hItem); if (Index != -1) dat->SelectedItems.RemoveElem(Index); // find an item to pass to SelectGroups() HTREEITEM hItem = TreeView_GetNextSibling(dat->hTreeView, pnmtv->itemOld.hItem); if (!hItem) { hItem = TreeView_GetPrevSibling(dat->hTreeView, pnmtv->itemOld.hItem); if (!hItem) hItem = TreeView_GetParent(dat->hTreeView, pnmtv->itemOld.hItem); } if (hItem) // if it wasn't one of the root items dat->SelectGroups(hItem, dat->SelectedItems.Find(hItem) != -1); NMCLIST nm; nm.hdr.code = MCLN_SELCHANGED; nm.hdr.hwndFrom = dat->hTreeView; nm.hdr.idFrom = GetDlgCtrlID(dat->hTreeView); nm.OldSelection = &OldSelection; nm.NewSelection = &dat->SelectedItems; SendMessage(hWnd, WM_NOTIFY, 0, (LPARAM)&nm); dat->Items[pnmtv->itemOld.lParam].hContact = INVALID_CONTACT_ID; } break; case NM_CUSTOMDRAW: LPNMTVCUSTOMDRAW lpNMCD = (LPNMTVCUSTOMDRAW)lParam; switch (lpNMCD->nmcd.dwDrawStage) { case CDDS_PREPAINT: // the control is about to start painting return CDRF_NOTIFYITEMDRAW; // instruct the control to return information when it draws items case CDDS_ITEMPREPAINT: return CDRF_NOTIFYPOSTPAINT; case CDDS_ITEMPOSTPAINT: RECT rc; if (TreeView_GetItemRect(dat->hTreeView, (HTREEITEM)lpNMCD->nmcd.dwItemSpec, &rc, false)) { for (int i = 0; i < MAXEXTRAICONS; i++) { BYTE nIndex = dat->Items[lpNMCD->nmcd.lItemlParam].ExtraIcons[i]; if (nIndex != CLC_EXTRAICON_EMPTY) { ImageList_DrawEx(dat->ExtraImageList, nIndex, lpNMCD->nmcd.hdc, rc.right - EXTRAICON_XSTEP * (i + 1), rc.top, 0, 0, /*GetSysColor(COLOR_WINDOW)*/CLR_NONE, CLR_NONE, ILD_NORMAL); } } } break; } } break; } } } return CallWindowProc(dat->OrigParentProc, hWnd, Msg, wParam, lParam); }
bool TreeCtrl::GetItemRect(HTREEITEM item, bool fItemRect, RECT& r) { BOOL ok = TreeView_GetItemRect(this->hwnd, item, &r, (BOOL)fItemRect); return fromBOOL(ok); }
LRESULT CALLBACK ContactListSubclassProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) { TVITEM tvi; CCList *dat = CWndUserData(GetParent(hWnd)).GetCList(); switch (Msg) { case INTM_CONTACTDELETED: // wParam = (HANDLE)hContact { HTREEITEM hItem = dat->FindContact(wParam); if (hItem) TreeView_DeleteItem(hWnd, hItem); } break; case INTM_ICONCHANGED: // wParam = (HANDLE)hContact, lParam = IconID tvi.hItem = dat->FindContact(wParam); if (tvi.hItem) { tvi.mask = TVIF_HANDLE | TVIF_IMAGE | TVIF_SELECTEDIMAGE; tvi.iImage = tvi.iSelectedImage = lParam; TreeView_SetItem(hWnd, &tvi); dat->SortContacts(); InvalidateRect(hWnd, nullptr, false); } break; case INTM_INVALIDATE: InvalidateRect(hWnd, nullptr, true); break; case WM_RBUTTONDOWN: SetFocus(hWnd); { TVHITTESTINFO hitTest; hitTest.pt.x = (short)LOWORD(lParam); hitTest.pt.y = (short)HIWORD(lParam); TreeView_HitTest(hWnd, &hitTest); if (hitTest.hItem && hitTest.flags & TVHT_ONITEM) TreeView_SelectItem(hWnd, hitTest.hItem); } return DefWindowProc(hWnd, Msg, wParam, lParam); case WM_LBUTTONDOWN: { POINT pt = { (short)LOWORD(lParam), (short)HIWORD(lParam) }; DWORD hitFlags; HTREEITEM hItem = dat->HitTest(&pt, &hitFlags); if (!hItem) break; if (hitFlags & MCLCHT_ONITEMICON) { if (TreeView_GetChild(hWnd, hItem)) { // if it's a group, then toggle its state NMTREEVIEW nmtv; nmtv.hdr.hwndFrom = hWnd; nmtv.hdr.idFrom = GetDlgCtrlID(hWnd); nmtv.hdr.code = TVN_ITEMEXPANDING; nmtv.action = TVE_TOGGLE; nmtv.itemNew.hItem = hItem; nmtv.itemNew.mask = TVIF_HANDLE | TVIF_STATE | TVIF_PARAM; TreeView_GetItem(hWnd, &nmtv.itemNew); nmtv.ptDrag = pt; if (SendMessage(GetParent(hWnd), WM_NOTIFY, 0, (LPARAM)&nmtv)) return 0; HTREEITEM hOldSelItem = TreeView_GetSelection(hWnd); TreeView_Expand(hWnd, hItem, TVE_TOGGLE); HTREEITEM hNewSelItem = TreeView_GetSelection(hWnd); if (hNewSelItem != hOldSelItem) { TreeView_SetItemState(hWnd, hOldSelItem, (dat->SelectedItems.Find(hOldSelItem) == -1) ? 0 : TVIS_SELECTED, TVIS_SELECTED); TreeView_SetItemState(hWnd, hNewSelItem, (dat->SelectedItems.Find(hNewSelItem) == -1) ? 0 : TVIS_SELECTED, TVIS_SELECTED); } nmtv.hdr.code = TVN_ITEMEXPANDED; TreeView_GetItem(hWnd, &nmtv.itemNew); SendMessage(GetParent(hWnd), WM_NOTIFY, 0, (LPARAM)&nmtv); return 0; } } if (hitFlags & MCLCHT_ONITEM) { if (wParam & MK_CONTROL) { SetFocus(hWnd); TREEITEMARRAY OldSelection = dat->SelectedItems; int nIndex = dat->SelectedItems.Find(hItem); if (nIndex == -1) { TreeView_SetItemState(hWnd, hItem, TVIS_SELECTED, TVIS_SELECTED); dat->SelectedItems.AddElem(hItem); } else { TreeView_SetItemState(hWnd, hItem, 0, TVIS_SELECTED); dat->SelectedItems.RemoveElem(nIndex); } dat->SelectGroups(hItem, nIndex == -1); NMCLIST nm; nm.hdr.code = MCLN_SELCHANGED; nm.hdr.hwndFrom = hWnd; nm.hdr.idFrom = GetDlgCtrlID(hWnd); nm.OldSelection = &OldSelection; nm.NewSelection = &dat->SelectedItems; SendMessage(GetParent(hWnd), WM_NOTIFY, 0, (LPARAM)&nm); return 0; } // if it was a click on the selected item and there's need to do something in this case, then send SELCHANGED notification by ourselves, as the tree control doesn't do anything if (hItem == TreeView_GetSelection(hWnd) && (dat->SelectedItems.GetSize() != 1 || (dat->SelectedItems.GetSize() == 1 && dat->SelectedItems[0] != hItem))) { TreeView_SetItemState(hWnd, hItem, TVIS_SELECTED, TVIS_SELECTED); NMTREEVIEW nm = {}; nm.hdr.code = TVN_SELCHANGED; nm.hdr.hwndFrom = hWnd; nm.hdr.idFrom = GetDlgCtrlID(hWnd); nm.itemOld.hItem = TreeView_GetSelection(hWnd); nm.itemOld.mask = TVIF_HANDLE | TVIF_STATE | TVIF_PARAM; TreeView_GetItem(hWnd, &nm.itemOld); nm.itemNew = nm.itemOld; SendMessage(GetParent(hWnd), WM_NOTIFY, 0, (LPARAM)&nm); } } } break; case WM_SETFOCUS: case WM_KILLFOCUS: for (int i = 0; i < dat->SelectedItems.GetSize(); i++) { RECT rc; if (TreeView_GetItemRect(hWnd, dat->SelectedItems[i], &rc, false)) InvalidateRect(hWnd, &rc, false); } break; case WM_SIZE: case WM_HSCROLL: InvalidateRect(hWnd, nullptr, false); break; case WM_MEASUREITEM: if (!wParam) // if the message was sent by a menu return Menu_MeasureItem(lParam); break; case WM_DRAWITEM: if (!wParam) // if the message was sent by a menu return Menu_DrawItem(lParam); break; case WM_CONTEXTMENU: { POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) }; HTREEITEM hItem = nullptr; if (pt.x == -1 && pt.y == -1) { if (dat->SelectedItems.GetSize() == 1) { hItem = dat->SelectedItems[0]; TreeView_EnsureVisible(hWnd, hItem); RECT rc; TreeView_GetItemRect(hWnd, hItem, &rc, true); pt.x = rc.left; pt.y = rc.bottom; } } else { DWORD hitFlags; ScreenToClient(hWnd, &pt); hItem = dat->HitTest(&pt, &hitFlags); if (!(hitFlags & MCLCHT_ONITEM)) hItem = nullptr; } if (hItem) { MCONTACT hContact = dat->GetItemData(hItem).hContact; if (IsHContactContact(hContact)) { HMENU hMenu = Menu_BuildContactMenu(hContact); if (hMenu) { ClientToScreen(hWnd, &pt); Clist_MenuProcessCommand(TrackPopupMenu(hMenu, TPM_LEFTALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD, pt.x, pt.y, 0, hWnd, nullptr), MPCF_CONTACTMENU, hContact); DestroyMenu(hMenu); return 0; } } } } break; case WM_DESTROY: if (dat->ExtraImageList) ImageList_Destroy(dat->ExtraImageList); dat->SelectedItems.RemoveAll(); dat->Items.RemoveAll(); break; } return CallWindowProc(dat->OrigTreeViewProc, hWnd, Msg, wParam, lParam); }
/******************************************************************************* * * FUNCTION: ChildWndProc(HWND, unsigned, WORD, LONG) * * PURPOSE: Processes messages for the child windows. * * WM_COMMAND - process the application menu * WM_PAINT - Paint the main window * WM_DESTROY - post a quit message and return * */ LRESULT CALLBACK ChildWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { BOOL Result; switch (message) { case WM_CREATE: { WNDPROC oldproc; HFONT hFont; WCHAR buffer[MAX_PATH]; /* Load "My Computer" string */ LoadStringW(hInst, IDS_MY_COMPUTER, buffer, COUNT_OF(buffer)); g_pChildWnd = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ChildWnd)); if (!g_pChildWnd) return 0; wcsncpy(g_pChildWnd->szPath, buffer, MAX_PATH); g_pChildWnd->nSplitPos = 250; g_pChildWnd->hWnd = hWnd; g_pChildWnd->hAddressBarWnd = CreateWindowExW(WS_EX_CLIENTEDGE, L"Edit", NULL, WS_CHILD | WS_VISIBLE | WS_CHILDWINDOW | WS_TABSTOP, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, hWnd, (HMENU)0, hInst, 0); g_pChildWnd->hAddressBtnWnd = CreateWindowExW(0, L"Button", L"»", WS_CHILD | WS_VISIBLE | WS_CHILDWINDOW | WS_TABSTOP | BS_TEXT | BS_CENTER | BS_VCENTER | BS_FLAT | BS_DEFPUSHBUTTON, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, hWnd, (HMENU)0, hInst, 0); g_pChildWnd->hTreeWnd = CreateTreeView(hWnd, g_pChildWnd->szPath, (HMENU) TREE_WINDOW); g_pChildWnd->hListWnd = CreateListView(hWnd, (HMENU) LIST_WINDOW/*, g_pChildWnd->szPath*/); SetFocus(g_pChildWnd->hTreeWnd); /* set the address bar and button font */ if ((g_pChildWnd->hAddressBarWnd) && (g_pChildWnd->hAddressBtnWnd)) { hFont = (HFONT)GetStockObject(DEFAULT_GUI_FONT); SendMessageW(g_pChildWnd->hAddressBarWnd, WM_SETFONT, (WPARAM)hFont, 0); SendMessageW(g_pChildWnd->hAddressBtnWnd, WM_SETFONT, (WPARAM)hFont, 0); } /* Subclass the AddressBar */ oldproc = (WNDPROC)(LONG_PTR)GetWindowLongPtr(g_pChildWnd->hAddressBarWnd, GWLP_WNDPROC); SetWindowLongPtr(g_pChildWnd->hAddressBarWnd, GWLP_USERDATA, (DWORD_PTR)oldproc); SetWindowLongPtr(g_pChildWnd->hAddressBarWnd, GWLP_WNDPROC, (DWORD_PTR)AddressBarProc); break; } case WM_COMMAND: if(HIWORD(wParam) == BN_CLICKED) { PostMessageW(g_pChildWnd->hAddressBarWnd, WM_KEYUP, VK_RETURN, 0); } if (!_CmdWndProc(hWnd, message, wParam, lParam)) { goto def; } break; case WM_PAINT: OnPaint(hWnd); return 0; case WM_SETCURSOR: if (LOWORD(lParam) == HTCLIENT) { POINT pt; GetCursorPos(&pt); ScreenToClient(hWnd, &pt); if (pt.x>=g_pChildWnd->nSplitPos-SPLIT_WIDTH/2 && pt.x<g_pChildWnd->nSplitPos+SPLIT_WIDTH/2+1) { SetCursor(LoadCursorW(0, IDC_SIZEWE)); return TRUE; } } goto def; case WM_DESTROY: DestroyTreeView(); DestroyListView(g_pChildWnd->hListWnd); DestroyMainMenu(); HeapFree(GetProcessHeap(), 0, g_pChildWnd); g_pChildWnd = NULL; PostQuitMessage(0); break; case WM_LBUTTONDOWN: { RECT rt; int x = (short)LOWORD(lParam); GetClientRect(hWnd, &rt); if (x>=g_pChildWnd->nSplitPos-SPLIT_WIDTH/2 && x<g_pChildWnd->nSplitPos+SPLIT_WIDTH/2+1) { last_split = g_pChildWnd->nSplitPos; draw_splitbar(hWnd, last_split); SetCapture(hWnd); } break; } case WM_LBUTTONUP: case WM_RBUTTONDOWN: if (GetCapture() == hWnd) { finish_splitbar(hWnd, LOWORD(lParam)); } break; case WM_CAPTURECHANGED: if (GetCapture()==hWnd && last_split>=0) draw_splitbar(hWnd, last_split); break; case WM_KEYDOWN: if (wParam == VK_ESCAPE) if (GetCapture() == hWnd) { RECT rt; draw_splitbar(hWnd, last_split); GetClientRect(hWnd, &rt); ResizeWnd(rt.right, rt.bottom); last_split = -1; ReleaseCapture(); SetCursor(LoadCursorW(0, IDC_ARROW)); } break; case WM_MOUSEMOVE: if (GetCapture() == hWnd) { HDC hdc; RECT rt; HGDIOBJ OldObj; int x = LOWORD(lParam); if(!SizingPattern) { const DWORD Pattern[4] = {0x5555AAAA, 0x5555AAAA, 0x5555AAAA, 0x5555AAAA}; SizingPattern = CreateBitmap(8, 8, 1, 1, Pattern); } if(!SizingBrush) { SizingBrush = CreatePatternBrush(SizingPattern); } GetClientRect(hWnd, &rt); x = (SHORT) min(max(x, SPLIT_MIN), rt.right - SPLIT_MIN); if(last_split != x) { rt.left = last_split-SPLIT_WIDTH/2; rt.right = last_split+SPLIT_WIDTH/2+1; hdc = GetDC(hWnd); OldObj = SelectObject(hdc, SizingBrush); PatBlt(hdc, rt.left, rt.top, rt.right - rt.left, rt.bottom - rt.top, PATINVERT); last_split = x; rt.left = x-SPLIT_WIDTH/2; rt.right = x+SPLIT_WIDTH/2+1; PatBlt(hdc, rt.left, rt.top, rt.right - rt.left, rt.bottom - rt.top, PATINVERT); SelectObject(hdc, OldObj); ReleaseDC(hWnd, hdc); } } break; case WM_SETFOCUS: if (g_pChildWnd != NULL) { SetFocus(g_pChildWnd->nFocusPanel? g_pChildWnd->hListWnd: g_pChildWnd->hTreeWnd); } break; case WM_TIMER: break; case WM_NOTIFY: if ((int)wParam == TREE_WINDOW && g_pChildWnd != NULL) { switch (((LPNMHDR)lParam)->code) { case TVN_ITEMEXPANDING: return !OnTreeExpanding(g_pChildWnd->hTreeWnd, (NMTREEVIEW*)lParam); case TVN_SELCHANGED: UpdateAddress(((NMTREEVIEW*)lParam)->itemNew.hItem, NULL, NULL); break; case NM_SETFOCUS: g_pChildWnd->nFocusPanel = 0; break; case TVN_BEGINLABELEDIT: { LPNMTVDISPINFO ptvdi; /* cancel label edit for rootkeys */ ptvdi = (LPNMTVDISPINFO) lParam; if (!TreeView_GetParent(g_pChildWnd->hTreeWnd, ptvdi->item.hItem) || !TreeView_GetParent(g_pChildWnd->hTreeWnd, TreeView_GetParent(g_pChildWnd->hTreeWnd, ptvdi->item.hItem))) return TRUE; break; } case TVN_ENDLABELEDIT: { LPCWSTR keyPath; HKEY hRootKey; HKEY hKey = NULL; LPNMTVDISPINFO ptvdi; LONG lResult = TRUE; WCHAR szBuffer[MAX_PATH]; ptvdi = (LPNMTVDISPINFO) lParam; if (ptvdi->item.pszText) { keyPath = GetItemPath(g_pChildWnd->hTreeWnd, TreeView_GetParent(g_pChildWnd->hTreeWnd, ptvdi->item.hItem), &hRootKey); _snwprintf(szBuffer, COUNT_OF(szBuffer), L"%s\\%s", keyPath, ptvdi->item.pszText); keyPath = GetItemPath(g_pChildWnd->hTreeWnd, ptvdi->item.hItem, &hRootKey); if (RegOpenKeyExW(hRootKey, szBuffer, 0, KEY_READ, &hKey) == ERROR_SUCCESS) { lResult = FALSE; RegCloseKey(hKey); (void)TreeView_EditLabel(g_pChildWnd->hTreeWnd, ptvdi->item.hItem); } else { if (RenameKey(hRootKey, keyPath, ptvdi->item.pszText) != ERROR_SUCCESS) lResult = FALSE; else UpdateAddress(ptvdi->item.hItem, hRootKey, szBuffer); } return lResult; } } default: return 0; } } else { if ((int)wParam == LIST_WINDOW && g_pChildWnd != NULL) { switch (((LPNMHDR)lParam)->code) { case NM_SETFOCUS: g_pChildWnd->nFocusPanel = 1; break; default: if(!ListWndNotifyProc(g_pChildWnd->hListWnd, wParam, lParam, &Result)) { goto def; } return Result; break; } } } break; case WM_CONTEXTMENU: { POINT pt; if((HWND)wParam == g_pChildWnd->hListWnd) { int i, cnt; BOOL IsDefault; pt.x = (short) LOWORD(lParam); pt.y = (short) HIWORD(lParam); cnt = ListView_GetSelectedCount(g_pChildWnd->hListWnd); i = ListView_GetNextItem(g_pChildWnd->hListWnd, -1, LVNI_FOCUSED | LVNI_SELECTED); if (pt.x == -1 && pt.y == -1) { RECT rc; if (i != -1) { rc.left = LVIR_BOUNDS; SendMessageW(g_pChildWnd->hListWnd, LVM_GETITEMRECT, i, (LPARAM) &rc); pt.x = rc.left + 8; pt.y = rc.top + 8; } else pt.x = pt.y = 0; ClientToScreen(g_pChildWnd->hListWnd, &pt); } if(i == -1) { TrackPopupMenu(GetSubMenu(hPopupMenus, PM_NEW), TPM_RIGHTBUTTON, pt.x, pt.y, 0, hFrameWnd, NULL); } else { HMENU mnu = GetSubMenu(hPopupMenus, PM_MODIFYVALUE); SetMenuDefaultItem(mnu, ID_EDIT_MODIFY, MF_BYCOMMAND); IsDefault = IsDefaultValue(g_pChildWnd->hListWnd, i); if(cnt == 1) EnableMenuItem(mnu, ID_EDIT_RENAME, MF_BYCOMMAND | (IsDefault ? MF_DISABLED | MF_GRAYED : MF_ENABLED)); else EnableMenuItem(mnu, ID_EDIT_RENAME, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED); EnableMenuItem(mnu, ID_EDIT_MODIFY, MF_BYCOMMAND | (cnt == 1 ? MF_ENABLED : MF_DISABLED | MF_GRAYED)); EnableMenuItem(mnu, ID_EDIT_MODIFY_BIN, MF_BYCOMMAND | (cnt == 1 ? MF_ENABLED : MF_DISABLED | MF_GRAYED)); TrackPopupMenu(mnu, TPM_RIGHTBUTTON, pt.x, pt.y, 0, hFrameWnd, NULL); } } else if ((HWND)wParam == g_pChildWnd->hTreeWnd) { TVHITTESTINFO hti; HMENU hContextMenu; TVITEMW item; MENUITEMINFOW mii; WCHAR resource[256]; WCHAR buffer[256]; LPWSTR s; LPCWSTR keyPath; HKEY hRootKey; int iLastPos; WORD wID; pt.x = (short) LOWORD(lParam); pt.y = (short) HIWORD(lParam); if (pt.x == -1 && pt.y == -1) { RECT rc; hti.hItem = TreeView_GetSelection(g_pChildWnd->hTreeWnd); if (hti.hItem != NULL) { TreeView_GetItemRect(g_pChildWnd->hTreeWnd, hti.hItem, &rc, TRUE); pt.x = rc.left + 8; pt.y = rc.top + 8; ClientToScreen(g_pChildWnd->hTreeWnd, &pt); hti.flags = TVHT_ONITEM; } else hti.flags = 0; } else { hti.pt.x = pt.x; hti.pt.y = pt.y; ScreenToClient(g_pChildWnd->hTreeWnd, &hti.pt); (void)TreeView_HitTest(g_pChildWnd->hTreeWnd, &hti); } if (hti.flags & TVHT_ONITEM) { hContextMenu = GetSubMenu(hPopupMenus, PM_TREECONTEXT); (void)TreeView_SelectItem(g_pChildWnd->hTreeWnd, hti.hItem); memset(&item, 0, sizeof(item)); item.mask = TVIF_STATE | TVIF_CHILDREN; item.hItem = hti.hItem; (void)TreeView_GetItem(g_pChildWnd->hTreeWnd, &item); /* Set the Expand/Collapse menu item appropriately */ LoadStringW(hInst, (item.state & TVIS_EXPANDED) ? IDS_COLLAPSE : IDS_EXPAND, buffer, COUNT_OF(buffer)); memset(&mii, 0, sizeof(mii)); mii.cbSize = sizeof(mii); mii.fMask = MIIM_STRING | MIIM_STATE | MIIM_ID; mii.fState = (item.cChildren > 0) ? MFS_DEFAULT : MFS_GRAYED; mii.wID = (item.state & TVIS_EXPANDED) ? ID_TREE_COLLAPSEBRANCH : ID_TREE_EXPANDBRANCH; mii.dwTypeData = (LPWSTR) buffer; SetMenuItemInfo(hContextMenu, 0, TRUE, &mii); /* Remove any existing suggestions */ memset(&mii, 0, sizeof(mii)); mii.cbSize = sizeof(mii); mii.fMask = MIIM_ID; GetMenuItemInfo(hContextMenu, GetMenuItemCount(hContextMenu) - 1, TRUE, &mii); if ((mii.wID >= ID_TREE_SUGGESTION_MIN) && (mii.wID <= ID_TREE_SUGGESTION_MAX)) { do { iLastPos = GetMenuItemCount(hContextMenu) - 1; GetMenuItemInfo(hContextMenu, iLastPos, TRUE, &mii); RemoveMenu(hContextMenu, iLastPos, MF_BYPOSITION); } while((mii.wID >= ID_TREE_SUGGESTION_MIN) && (mii.wID <= ID_TREE_SUGGESTION_MAX)); } /* Come up with suggestions */ keyPath = GetItemPath(g_pChildWnd->hTreeWnd, NULL, &hRootKey); SuggestKeys(hRootKey, keyPath, Suggestions, COUNT_OF(Suggestions)); if (Suggestions[0]) { AppendMenu(hContextMenu, MF_SEPARATOR, 0, NULL); LoadStringW(hInst, IDS_GOTO_SUGGESTED_KEY, resource, COUNT_OF(resource)); s = Suggestions; wID = ID_TREE_SUGGESTION_MIN; while(*s && (wID <= ID_TREE_SUGGESTION_MAX)) { _snwprintf(buffer, COUNT_OF(buffer), resource, s); memset(&mii, 0, sizeof(mii)); mii.cbSize = sizeof(mii); mii.fMask = MIIM_STRING | MIIM_ID; mii.wID = wID++; mii.dwTypeData = buffer; InsertMenuItem(hContextMenu, GetMenuItemCount(hContextMenu), TRUE, &mii); s += wcslen(s) + 1; } } TrackPopupMenu(hContextMenu, TPM_RIGHTBUTTON, pt.x, pt.y, 0, g_pChildWnd->hWnd, NULL); } } break; } case WM_SIZE: if (wParam != SIZE_MINIMIZED && g_pChildWnd != NULL) { ResizeWnd(LOWORD(lParam), HIWORD(lParam)); } /* fall through */ default: def: return DefWindowProcW(hWnd, message, wParam, lParam); } return 0; }
static void RelayoutTocItem(LPNMTVCUSTOMDRAW ntvcd) { // code inspired by http://www.codeguru.com/cpp/controls/treeview/multiview/article.php/c3985/ LPNMCUSTOMDRAW ncd = &ntvcd->nmcd; HWND hTV = ncd->hdr.hwndFrom; HTREEITEM hItem = (HTREEITEM)ncd->dwItemSpec; RECT rcItem; if (0 == ncd->rc.right - ncd->rc.left || 0 == ncd->rc.bottom - ncd->rc.top) return; if (!TreeView_GetItemRect(hTV, hItem, &rcItem, TRUE)) return; if (rcItem.right > ncd->rc.right) rcItem.right = ncd->rc.right; // Clear the label RECT rcFullWidth = rcItem; rcFullWidth.right = ncd->rc.right; FillRect(ncd->hdc, &rcFullWidth, GetSysColorBrush(COLOR_WINDOW)); // Get the label's text WCHAR szText[MAX_PATH]; TVITEM item; item.hItem = hItem; item.mask = TVIF_TEXT | TVIF_PARAM; item.pszText = szText; item.cchTextMax = MAX_PATH; TreeView_GetItem(hTV, &item); // Draw the page number right-aligned (if there is one) WindowInfo *win = FindWindowInfoByHwnd(hTV); DocTocItem *tocItem = (DocTocItem *)item.lParam; ScopedMem<WCHAR> label; if (tocItem->pageNo && win && win->IsDocLoaded()) { label.Set(win->ctrl->GetPageLabel(tocItem->pageNo)); label.Set(str::Join(L" ", label)); } if (label && str::EndsWith(item.pszText, label)) { RECT rcPageNo = rcFullWidth; InflateRect(&rcPageNo, -2, -1); SIZE txtSize; GetTextExtentPoint32(ncd->hdc, label, str::Len(label), &txtSize); rcPageNo.left = rcPageNo.right - txtSize.cx; SetTextColor(ncd->hdc, GetSysColor(COLOR_WINDOWTEXT)); SetBkColor(ncd->hdc, GetSysColor(COLOR_WINDOW)); DrawText(ncd->hdc, label, -1, &rcPageNo, DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX); // Reduce the size of the label and cut off the page number rcItem.right = std::max(rcItem.right - txtSize.cx, 0); szText[str::Len(szText) - str::Len(label)] = '\0'; } SetTextColor(ncd->hdc, ntvcd->clrText); SetBkColor(ncd->hdc, ntvcd->clrTextBk); // Draw the focus rectangle (including proper background color) HBRUSH brushBg = CreateSolidBrush(ntvcd->clrTextBk); FillRect(ncd->hdc, &rcItem, brushBg); DeleteObject(brushBg); if ((ncd->uItemState & CDIS_FOCUS)) DrawFocusRect(ncd->hdc, &rcItem); InflateRect(&rcItem, -2, -1); DrawText(ncd->hdc, szText, -1, &rcItem, DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX | DT_WORD_ELLIPSIS); }
/* * MainWindowProc * * Purpose: * * Main window procedure. * */ LRESULT CALLBACK MainWindowProc( _In_ HWND hwnd, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam ) { INT mark; RECT ToolBarRect, crc; LPDRAWITEMSTRUCT pds; LPMEASUREITEMSTRUCT pms; switch (uMsg) { case WM_CONTEXTMENU: RtlSecureZeroMemory(&crc, sizeof(crc)); if ((HWND)wParam == g_hwndObjectTree) { TreeView_GetItemRect(g_hwndObjectTree, TreeView_GetSelection(g_hwndObjectTree), &crc, TRUE); crc.top = crc.bottom; ClientToScreen(g_hwndObjectTree, (LPPOINT)&crc); supHandleTreePopupMenu(hwnd, (LPPOINT)&crc); } if ((HWND)wParam == g_hwndObjectList) { mark = ListView_GetSelectionMark(g_hwndObjectList); if (lParam == MAKELPARAM(-1, -1)) { ListView_GetItemRect(g_hwndObjectList, mark, &crc, TRUE); crc.top = crc.bottom; ClientToScreen(g_hwndObjectList, (LPPOINT)&crc); } else GetCursorPos((LPPOINT)&crc); supHandleObjectPopupMenu(hwnd, g_hwndObjectList, mark, (LPPOINT)&crc); } break; case WM_COMMAND: MainWindowHandleWMCommand(hwnd, wParam, lParam); break; case WM_NOTIFY: MainWindowHandleWMNotify(hwnd, wParam, lParam); break; case WM_MEASUREITEM: pms = (LPMEASUREITEMSTRUCT)lParam; if (pms && pms->CtlType == ODT_MENU) { pms->itemWidth = 16; pms->itemHeight = 16; } break; case WM_DRAWITEM: pds = (LPDRAWITEMSTRUCT)lParam; if (pds && pds->CtlType == ODT_MENU) { DrawIconEx(pds->hDC, pds->rcItem.left - 15, pds->rcItem.top, (HICON)pds->itemData, 16, 16, 0, NULL, DI_NORMAL); } break; case WM_CLOSE: PostQuitMessage(0); break; case WM_LBUTTONDOWN: SetCapture(MainWindow); break; case WM_LBUTTONUP: ReleaseCapture(); break; case WM_MOUSEMOVE: if ((wParam & MK_LBUTTON) != 0) { GetClientRect(MainWindow, &ToolBarRect); SplitterPos = (SHORT)LOWORD(lParam); if (SplitterPos < SplitterMargin) SplitterPos = SplitterMargin; if (SplitterPos > ToolBarRect.right - SplitterMargin) SplitterPos = ToolBarRect.right - SplitterMargin; SendMessage(MainWindow, WM_SIZE, 0, 0); UpdateWindow(MainWindow); } break; case WM_SIZE: if (!IsIconic(hwnd)) { MainWindowResizeHandler(SplitterPos); } break; case WM_GETMINMAXINFO: if (lParam) { ((PMINMAXINFO)lParam)->ptMinTrackSize.x = 400; ((PMINMAXINFO)lParam)->ptMinTrackSize.y = 256; } break; } return DefWindowProc(hwnd, uMsg, wParam, lParam); }
static LRESULT CALLBACK WndProc (HWND hwnd, UINT uMessage, WPARAM wParam, LPARAM lParam) { static bool bDragging = FALSE; switch (uMessage) { case WM_SETFOCUS: case WM_KILLFOCUS: { mxWindow *window = (mxWindow *) GetWindowLong (hwnd, GWL_USERDATA); if ( window ) { mxEvent event; event.event = mxEvent::Focus; event.widget = NULL; event.action = (uMessage == WM_SETFOCUS); RecursiveHandleEvent( window, &event ); return 0; } } break; case WM_ACTIVATE: { mxWindow *window = (mxWindow *) GetWindowLong (hwnd, GWL_USERDATA); if ( window ) { mxEvent event; event.event = mxEvent::Activate; event.widget = NULL; event.action = (LOWORD( wParam ) != WA_INACTIVE); RecursiveHandleEvent( window, &event ); return 0; } } break; case WM_COMMAND: { mxWindow *window = (mxWindow *) GetWindowLong (hwnd, GWL_USERDATA); if (LOWORD (wParam) > 0 && window) { WORD wNotifyCode = (WORD) HIWORD (wParam); HWND hwndCtrl = (HWND) lParam; mxEvent event; CHAR className[128]; GetClassName (hwndCtrl, className, 128); if (!strcmpi (className, "edit")) { if (wNotifyCode != EN_CHANGE) break; } else if (!strcmpi (className, "combobox")) { if (wNotifyCode != CBN_SELCHANGE) break; } else if (!strcmpi (className, "listbox")) { if (wNotifyCode != LBN_SELCHANGE) break; } event.event = mxEvent::Action; event.widget = (mxWidget *) GetWindowLong ((HWND) lParam, GWL_USERDATA); event.action = (int) LOWORD (wParam); RecursiveHandleEvent( window, &event ); } } break; case WM_NOTIFY: { if (isClosing) break; NMHDR *nmhdr = (NMHDR *) lParam; mxEvent event; #if 0 //if ( nmhdr->idFrom > 0 ) { mxWidget *temp = (mxWidget *) GetWindowLong (nmhdr->hwndFrom, GWL_USERDATA); if ( temp && temp->getType() == MX_TREEVIEW ) { NMTREEVIEW *nmt = ( NMTREEVIEW * )nmhdr; HTREEITEM hItem = TreeView_GetSelection (nmhdr->hwndFrom); char sz[ 256 ]; sprintf( sz, "tree view receiving notify %i : %s action %i old %p new %p selection %p\n", nmhdr->code, translatecode( nmhdr->code ), nmt->action, nmt->itemOld, nmt->itemNew, hItem ); OutputDebugString( sz ); } } #endif if (nmhdr->code == TVN_SELCHANGED) { if (nmhdr->idFrom > 0) { mxWindow *window = (mxWindow *) GetWindowLong (hwnd, GWL_USERDATA); event.event = mxEvent::Action; event.widget = (mxWidget *) GetWindowLong (nmhdr->hwndFrom, GWL_USERDATA); event.action = (int) nmhdr->idFrom; RECT rc; HTREEITEM hItem = TreeView_GetSelection (nmhdr->hwndFrom); TreeView_GetItemRect (nmhdr->hwndFrom, hItem, &rc, TRUE); event.x = (int) rc.left; event.y = (int) rc.bottom; RecursiveHandleEvent( window, &event ); } } else if (nmhdr->code == LVN_ITEMCHANGED) { if (nmhdr->idFrom > 0) { mxWindow *window = (mxWindow *) GetWindowLong (hwnd, GWL_USERDATA); event.event = mxEvent::Action; event.widget = (mxWidget *) GetWindowLong (nmhdr->hwndFrom, GWL_USERDATA); event.action = (int) nmhdr->idFrom; RecursiveHandleEvent( window, &event ); } } else if (nmhdr->code == NM_RCLICK) { if (nmhdr->idFrom > 0) { mxWindow *window = (mxWindow *) GetWindowLong (hwnd, GWL_USERDATA); event.event = mxEvent::Action; event.widget = (mxWidget *) GetWindowLong (nmhdr->hwndFrom, GWL_USERDATA); event.action = (int) nmhdr->idFrom; event.flags = mxEvent::RightClicked; if ( event.widget ) { if ( event.widget->getType () == MX_TREEVIEW ) { RECT rc; HTREEITEM hItem = TreeView_GetSelection (nmhdr->hwndFrom); TreeView_GetItemRect (nmhdr->hwndFrom, hItem, &rc, TRUE); event.x = (int) rc.left; event.y = (int) rc.bottom; } } RecursiveHandleEvent( window, &event ); } } else if (nmhdr->code == NM_DBLCLK) { if (nmhdr->idFrom > 0) { mxWindow *window = (mxWindow *) GetWindowLong (hwnd, GWL_USERDATA); event.event = mxEvent::Action; event.widget = (mxWidget *) GetWindowLong (nmhdr->hwndFrom, GWL_USERDATA); event.action = (int) nmhdr->idFrom; event.flags = mxEvent::DoubleClicked; if (event.widget ) { if ( event.widget->getType () == MX_TREEVIEW ) { RECT rc; HTREEITEM hItem = TreeView_GetSelection (nmhdr->hwndFrom); TreeView_GetItemRect (nmhdr->hwndFrom, hItem, &rc, TRUE); event.x = (int) rc.left; event.y = (int) rc.bottom; } } RecursiveHandleEvent( window, &event ); return TRUE; } } else if (nmhdr->code == TCN_SELCHANGING) { TC_ITEM ti; int index = TabCtrl_GetCurSel (nmhdr->hwndFrom); if (index >= 0) { ti.mask = TCIF_PARAM; TabCtrl_GetItem (nmhdr->hwndFrom, index, &ti); mxWindow *window = (mxWindow *) ti.lParam; if (window) window->setVisible (false); } } else if (nmhdr->code == TCN_SELCHANGE) { mxTab_resizeChild (nmhdr->hwndFrom); if (nmhdr->idFrom > 0) { mxWindow *window = (mxWindow *) GetWindowLong (hwnd, GWL_USERDATA); event.event = mxEvent::Action; event.widget = (mxWidget *) GetWindowLong (nmhdr->hwndFrom, GWL_USERDATA); event.action = (int) nmhdr->idFrom; RecursiveHandleEvent( window, &event ); } } } break; case WM_SIZE: { mxEvent event; mxWindow *window = (mxWindow *) GetWindowLong (hwnd, GWL_USERDATA); if (window) { event.event = mxEvent::Size; event.width = (int) LOWORD (lParam); event.height = (int) HIWORD (lParam); window->handleEvent (&event); } } break; case WM_WINDOWPOSCHANGED: { mxEvent event; mxWindow *window = (mxWindow *) GetWindowLong (hwnd, GWL_USERDATA); if (window) { event.event = mxEvent::PosChanged; WINDOWPOS *wp = ( WINDOWPOS * )lParam; event.x = wp->x; event.y = wp->y; event.width = wp->cx; event.height = wp->cy; window->handleEvent (&event); } } break; case WM_ERASEBKGND: { mxWindow *window = (mxWindow *) GetWindowLong (hwnd, GWL_USERDATA); if (window) { if (window->getType () == MX_GLWINDOW) return 0; if (window->getType () == MX_MATSYSWINDOW) return 0; if ( !isClosing && !window->PaintBackground() ) { return 0; } } } break; case WM_HSCROLL: case WM_VSCROLL: { mxWidget *widget = (mxWidget *) GetWindowLong ((HWND) lParam, GWL_USERDATA); if (!widget) { break; } if (widget->getType() != MX_SCROLLBAR && widget->getType() != MX_SLIDER) { break; } switch (LOWORD (wParam)) { case TB_LINEUP: // SB_LINEUP SB_LINELEFT break; case TB_LINEDOWN: // SB_LINEDOWN SB_LINERIGHT break; case TB_PAGEUP: // SB_PAGEUP SB_PAGELEFT break; case TB_PAGEDOWN: // SB_PAGEDOWN SB_PAGERIGHT break; case TB_THUMBPOSITION: // SB_THUMBPOSITION break; case TB_THUMBTRACK: // SB_THUMBTRACK break; case TB_TOP: // SB_TOP SB_LEFT break; case TB_BOTTOM: // SB_BOTTOM SB_RIGHT break; case TB_ENDTRACK: // SB_ENDSCROLL break; default: break; } switch (LOWORD (wParam)) { case TB_LINEUP: // SB_LINEUP SB_LINELEFT case TB_LINEDOWN: // SB_LINEDOWN SB_LINERIGHT case TB_PAGEUP: // SB_PAGEUP SB_PAGELEFT case TB_PAGEDOWN: // SB_PAGEDOWN SB_PAGERIGHT case TB_THUMBPOSITION: // SB_THUMBPOSITION case TB_THUMBTRACK: // SB_THUMBTRACK case TB_TOP: // SB_TOP SB_LEFT case TB_BOTTOM: // SB_BOTTOM SB_RIGHT case TB_ENDTRACK: // SB_ENDSCROLL { mxEvent event; event.event = mxEvent::Action; event.widget = widget; event.action = widget->getId (); event.modifiers = LOWORD (wParam); event.height = HIWORD( wParam ); mxWindow *window = widget->getParent (); if ( event.action > 0 ) { RecursiveHandleEvent( window, &event ); } } break; } } break; case WM_PAINT: { if ( !isClosing ) { mxWindow *window = (mxWindow *) GetWindowLong (hwnd, GWL_USERDATA); if (window) { window->redraw (); } } } break; case WM_PARENTNOTIFY: { mxWindow *window = (mxWindow *) GetWindowLong (hwnd, GWL_USERDATA); if (window) { if ( wParam == WM_LBUTTONDOWN || wParam == WM_MBUTTONDOWN || wParam == WM_RBUTTONDOWN /*|| wParam & WM_XBUTTONDOWN*/ ) { mxEvent event; event.event = mxEvent::ParentNotify; event.x = (short)LOWORD (lParam); event.y = (short)HIWORD (lParam); event.buttons = 0; event.modifiers = 0; if ( wParam == WM_LBUTTONDOWN ) event.buttons |= mxEvent::MouseLeftButton; if ( wParam == WM_RBUTTONDOWN ) event.buttons |= mxEvent::MouseRightButton; if ( wParam == WM_MBUTTONDOWN ) event.buttons |= mxEvent::MouseMiddleButton; window->handleEvent (&event); RecursiveHandleEvent( window, &event ); return 0; } } } break; case WM_LBUTTONDOWN: case WM_MBUTTONDOWN: case WM_RBUTTONDOWN: { bDragging = TRUE; SetCapture (hwnd); mxWindow *window = (mxWindow *) GetWindowLong (hwnd, GWL_USERDATA); if (window) { mxEvent event; event.event = mxEvent::MouseDown; event.x = (short)LOWORD (lParam); event.y = (short)HIWORD (lParam); event.buttons = 0; event.modifiers = 0; if (uMessage == WM_MBUTTONDOWN) event.buttons |= mxEvent::MouseMiddleButton; else if (uMessage == WM_RBUTTONDOWN) event.buttons |= mxEvent::MouseRightButton; else event.buttons |= mxEvent::MouseLeftButton; if (wParam & MK_LBUTTON) event.buttons |= mxEvent::MouseLeftButton; if (wParam & MK_RBUTTON) event.buttons |= mxEvent::MouseRightButton; if (wParam & MK_MBUTTON) event.buttons |= mxEvent::MouseMiddleButton; if (wParam & MK_CONTROL) event.modifiers |= mxEvent::KeyCtrl; if (wParam & MK_SHIFT) event.modifiers |= mxEvent::KeyShift; window->handleEvent (&event); } } break; case WM_LBUTTONUP: case WM_MBUTTONUP: case WM_RBUTTONUP: { mxWindow *window = (mxWindow *) GetWindowLong (hwnd, GWL_USERDATA); if (window) { mxEvent event; event.event = mxEvent::MouseUp; event.x = (short) LOWORD (lParam); event.y = (short) HIWORD (lParam); event.buttons = 0; event.modifiers = 0; if (uMessage == WM_MBUTTONUP) event.buttons |= mxEvent::MouseMiddleButton; else if (uMessage == WM_RBUTTONUP) event.buttons |= mxEvent::MouseRightButton; else event.buttons |= mxEvent::MouseLeftButton; if (wParam & MK_LBUTTON) event.buttons |= mxEvent::MouseLeftButton; if (wParam & MK_RBUTTON) event.buttons |= mxEvent::MouseRightButton; if (wParam & MK_MBUTTON) event.buttons |= mxEvent::MouseMiddleButton; if (wParam & MK_CONTROL) event.modifiers |= mxEvent::KeyCtrl; if (wParam & MK_SHIFT) event.modifiers |= mxEvent::KeyShift; window->handleEvent (&event); } bDragging = FALSE; ReleaseCapture (); } break; case WM_MOUSEMOVE: { mxWindow *window = (mxWindow *) GetWindowLong (hwnd, GWL_USERDATA); if (window) { mxEvent event; if (bDragging) event.event = mxEvent::MouseDrag; else event.event = mxEvent::MouseMove; event.x = (short) LOWORD (lParam); event.y = (short) HIWORD (lParam); event.buttons = 0; event.modifiers = 0; if (wParam & MK_LBUTTON) event.buttons |= mxEvent::MouseLeftButton; if (wParam & MK_RBUTTON) event.buttons |= mxEvent::MouseRightButton; if (wParam & MK_MBUTTON) event.buttons |= mxEvent::MouseMiddleButton; if (wParam & MK_CONTROL) event.modifiers |= mxEvent::KeyCtrl; if (wParam & MK_SHIFT) event.modifiers |= mxEvent::KeyShift; window->handleEvent (&event); } } break; case WM_NCLBUTTONDOWN: case WM_NCMBUTTONDOWN: case WM_NCRBUTTONDOWN: { mxWindow *window = (mxWindow *) GetWindowLong (hwnd, GWL_USERDATA); if (window) { mxEvent event; event.event = mxEvent::NCMouseDown; event.x = (short) LOWORD (lParam); event.y = (short) HIWORD (lParam); event.buttons = 0; event.modifiers = 0; if (uMessage == WM_NCMBUTTONDOWN) event.buttons |= mxEvent::MouseMiddleButton; else if (uMessage == WM_NCRBUTTONDOWN) event.buttons |= mxEvent::MouseRightButton; else event.buttons |= mxEvent::MouseLeftButton; window->handleEvent (&event); } } break; case WM_NCLBUTTONUP: case WM_NCMBUTTONUP: case WM_NCRBUTTONUP: { mxWindow *window = (mxWindow *) GetWindowLong (hwnd, GWL_USERDATA); if (window) { mxEvent event; event.event = mxEvent::NCMouseUp; event.x = (short) LOWORD (lParam); event.y = (short) HIWORD (lParam); event.buttons = 0; event.modifiers = 0; if (uMessage == WM_NCMBUTTONUP) event.buttons |= mxEvent::MouseMiddleButton; else if (uMessage == WM_NCRBUTTONUP) event.buttons |= mxEvent::MouseRightButton; else event.buttons |= mxEvent::MouseLeftButton; window->handleEvent (&event); } } break; case WM_NCMOUSEMOVE: { mxWindow *window = (mxWindow *) GetWindowLong (hwnd, GWL_USERDATA); if (window) { mxEvent event; event.event = mxEvent::NCMouseMove; event.x = (short) LOWORD (lParam); event.y = (short) HIWORD (lParam); event.buttons = 0; event.modifiers = 0; window->handleEvent (&event); } } break; case WM_KEYDOWN: case WM_SYSKEYDOWN: { mxWindow *window = (mxWindow *) GetWindowLong (hwnd, GWL_USERDATA); if (window) { mxEvent event; event.event = mxEvent::KeyDown; event.key = (int) wParam; if ( window->handleEvent (&event) ) return 0; } } break; case WM_CHAR: { mxWindow *window = (mxWindow *) GetWindowLong (hwnd, GWL_USERDATA); if (window) { mxEvent event; event.event = mxEvent::Char; event.key = (int) wParam; if ( window->handleEvent (&event) ) return 0; } } break; case WM_SYSCHAR: return 0; break; case WM_KEYUP: case WM_SYSKEYUP: { mxWindow *window = (mxWindow *) GetWindowLong (hwnd, GWL_USERDATA); if (window) { mxEvent event; event.event = mxEvent::KeyUp; event.key = (int) wParam; if ( window->handleEvent (&event) ) return 0; } } break; case WM_MOUSEWHEEL: { mxWindow *window = (mxWindow *) GetWindowLong (hwnd, GWL_USERDATA); if (window) { mxEvent event; memset( &event, 0, sizeof( event ) ); event.event = mxEvent::MouseWheeled; event.x = (short) LOWORD (lParam); event.y = (short) HIWORD (lParam); if (wParam & MK_LBUTTON) event.buttons |= mxEvent::MouseLeftButton; if (wParam & MK_RBUTTON) event.buttons |= mxEvent::MouseRightButton; if (wParam & MK_MBUTTON) event.buttons |= mxEvent::MouseMiddleButton; if (wParam & MK_CONTROL) event.modifiers |= mxEvent::KeyCtrl; if (wParam & MK_SHIFT) event.modifiers |= mxEvent::KeyShift; event.height = (short)HIWORD( wParam );; RecursiveHandleEvent( window, &event ); } } break; case WM_TIMER: { if (isClosing) break; mxWindow *window = (mxWindow *) GetWindowLong (hwnd, GWL_USERDATA); if (window) { mxEvent event; event.event = mxEvent::Timer; window->handleEvent (&event); } } break; case WM_CLOSE: if (g_mainWindow) { if ((void *) hwnd == g_mainWindow->getHandle ()) { mx::quit (); } else { ShowWindow (hwnd, SW_HIDE); mxWindow *window = (mxWindow *) GetWindowLong (hwnd, GWL_USERDATA); if (window) { mxEvent event; event.event = mxEvent::Close; window->handleEvent( &event ); } } } //else // shouldn't happen //DestroyWindow (hwnd); return 0; /* case WM_DESTROY: if (g_mainWindow) { if ((void *) hwnd == g_mainWindow->getHandle ()) mx::quit (); } break; */ } return DefWindowProc (hwnd, uMessage, wParam, lParam); }
LRESULT CALLBACK extTreeWndProc(HWND hwnd, UINT iMessage, WPARAM wParam, LPARAM lParam) { static char buf[256]; LRESULT rv; RECT r; TREEINFO *ptr; HTREEITEM hTreeItem; TCData *td; TV_HITTESTINFO tvh; TV_ITEM item; NM_TREEVIEW x; switch (iMessage) { case WM_NOTIFY: // if (((NMHDR*)lParam)->code == TVN_SELCHANGING) // return TRUE; break; case WM_CREATE: ptr = (TREEINFO*)calloc(1,sizeof(TREEINFO)); ptr->hwndEdit = 0; SetWindowLong(hwnd, wndoffstree, (int)ptr); break; case WM_DESTROY: ptr = (TREEINFO*)GetWindowLong(hwnd, wndoffstree); if (ptr->hwndEdit) DestroyWindow(ptr->hwndEdit); free(ptr); break; case WM_ERASEBKGND: return 1; case WM_PAINT: GetUpdateRect(hwnd, &r, FALSE); { PAINTSTRUCT ps; HDC hDC = BeginPaint(hwnd, &ps), hdouble; HBITMAP bitmap; RECT rect; GetClientRect(hwnd, &rect); hdouble = CreateCompatibleDC(hDC); bitmap = CreateCompatibleBitmap(hDC, rect.right, rect.bottom); SelectObject(hdouble, bitmap); FillRect(hdouble,&rect, (HBRUSH)(COLOR_WINDOW + 1)); CallWindowProc(oldproc, hwnd, WM_PRINT, (WPARAM)hdouble, PRF_CLIENT); SendMessage(GetParent(hwnd), TCN_PAINT, (WPARAM)hdouble, (LPARAM) &r); BitBlt(hDC, 0, 0, rect.right, rect.bottom, hdouble, 0, 0, SRCCOPY); DeleteObject(bitmap); DeleteDC(hdouble); EndPaint(hwnd, &ps); return 0; } case WM_KEYDOWN: if (wParam =='C' && (GetKeyState(VK_CONTROL) & 0x80000000)) { CopyText(hwnd); } break; case WM_SETFOCUS: SendMessage(GetParent(hwnd), WM_ACTIVATEME, 0, 0); break; case WM_CHAR: if (wParam == 3) //CTRL-C - this is being done to stop beeping... return 0; break; case WM_LBUTTONDOWN: ptr = (TREEINFO*)GetWindowLong(hwnd, wndoffstree); if (!ptr->hwndEdit) { tvh.pt.x = LOWORD(lParam); tvh.pt.y = HIWORD(lParam); if (tvh.pt.x < ptr->divider) { SetFocus(hwnd); break; } TreeView_HitTest(hwnd, &tvh); hTreeItem = tvh.hItem; if (hTreeItem && tvh.pt.x >= ptr->divider) { char *val; x.hdr.code = TCN_EDITQUERY; x.itemOld.mask = 0; x.itemNew.mask = 0; x.itemNew.hItem = hTreeItem; if ((val = (char*)SendMessage(GetParent(hwnd), WM_NOTIFY, 0, (LPARAM) &x))) { HFONT font = (HFONT)SendMessage(hwnd, WM_GETFONT, 0, 0); ptr->editItem = hTreeItem; TreeView_GetItemRect(hwnd, hTreeItem, &r, FALSE); r.left = ptr->divider; item.hItem = hTreeItem; item.mask = TVIF_PARAM; TreeView_GetItem(hwnd, &item); td = (TCData*)item.lParam; ptr->hwndEdit = CreateWindow(szextEditWindClassName, val, WS_CHILD | ES_AUTOHSCROLL, r.left+2, r.top, r.right - r.left-2, r.bottom - r.top, hwnd, (HMENU) 449, (HINSTANCE)GetWindowLong(GetParent(hwnd), GWL_HINSTANCE), 0); SendMessage(ptr->hwndEdit, WM_SETFONT, (WPARAM)font, MAKELPARAM(0, 0)); SendMessage(ptr->hwndEdit, EM_SETSEL, 0, (LPARAM) - 1); SendMessage(ptr->hwndEdit, EM_SETLIMITTEXT, 40, 0); ShowWindow(ptr->hwndEdit, SW_SHOW); SetFocus(ptr->hwndEdit); return 0; } } return 0; } // FALL THROUGH case TCN_EDITDONE: ptr = (TREEINFO*)GetWindowLong(hwnd, wndoffstree); SendMessage(ptr->hwndEdit, WM_GETTEXT, 50, (LPARAM)buf); DestroyWindow(ptr->hwndEdit); ptr->hwndEdit = 0; x.hdr.code = TCN_EDITDONE; x.itemOld.mask = 0; x.itemNew.mask = TVIF_TEXT; x.itemNew.hItem = ptr->editItem; x.itemNew.pszText = buf; SendMessage(GetParent(hwnd), WM_NOTIFY, 0, (LPARAM) &x); InvalidateRect(GetParent(hwnd), 0, 0); return 0; case TCF_SETDIVIDER: ptr = (TREEINFO*)GetWindowLong(hwnd, wndoffstree); ptr->divider = lParam - GetSystemMetrics(SM_CXBORDER); return 0; } return CallWindowProc(oldproc, hwnd, iMessage, wParam, lParam); }
LRESULT CALLBACK ColumnTreeWndProc(HWND hwnd, UINT iMessage, WPARAM wParam, LPARAM lParam) { HTREEITEM titem; HD_LAYOUT hdl; WINDOWPOS wp; COLUMNINFO *ptr; RECT r, *rp; HD_ITEM hie; TCHeader *h; HD_NOTIFY *n; TV_DISPINFO *t; LPTV_INSERTSTRUCT is; int i; TV_ITEM item; TCData *td; TV_HITTESTINFO tvh; TREEINFO *treeinfo; PAINTSTRUCT ps; HDC dc; NM_TREEVIEW *ntv; if (iMessage >= TV_FIRST && iMessage < TV_FIRST + 100) { ptr = (COLUMNINFO*)GetWindowLong(hwnd, 0); switch (iMessage) { case TVM_HITTEST: tvh.pt = ((TV_HITTESTINFO*)lParam)->pt; ptr = (COLUMNINFO*)GetWindowLong(hwnd, 0); GetRelativeRect(hwnd, ptr->hwndTree, &r); tvh.pt.x -= r.left; tvh.pt.y -= r.top; if ((titem = TreeView_HitTest(ptr->hwndTree, &tvh))) { ((TV_HITTESTINFO*)lParam)->flags = tvh.flags; ((TV_HITTESTINFO*)lParam)->hItem = tvh.hItem; } return (LRESULT)titem; case TVM_INSERTITEM: is = (LPTV_INSERTSTRUCT)lParam; is->UNNAMED_UNION item.mask |= TVIF_TEXT | TVIF_PARAM; is->UNNAMED_UNION item.pszText = LPSTR_TEXTCALLBACK; titem = (HTREEITEM)SendMessage(ptr->hwndTree, iMessage, wParam, lParam); return (LRESULT)titem; default: return SendMessage(ptr->hwndTree, iMessage, wParam, lParam); } } else if (iMessage >= HDM_FIRST && iMessage < HDM_FIRST + 100) { ptr = (COLUMNINFO*)GetWindowLong(hwnd, 0); return SendMessage(ptr->hwndHeader, iMessage, wParam, lParam); } switch (iMessage) { case WM_ERASEBKGND: return 1; case WM_NOTIFY: n = (HD_NOTIFY*)lParam; ptr = (COLUMNINFO*)GetWindowLong(hwnd, 0); switch (n->hdr.code) { case NM_RCLICK: #ifdef XXXXX ptr = (COLUMNINFO*)GetWindowLong(hwnd, 0); GetCursorPos(&pos); ScreenToClient(ptr->hwndTree, &pos); titem = TreeView_HitTest(ptr->hwndTree, &pos); for (i = 0; i < ptr->displaycount; i++) if (titem == ptr->displaylist[i]) { ptr->sel = i; InvalidateRect(ptr->hwndTree, 0, 0); break; } #endif return SendMessage(GetParent(hwnd), iMessage, wParam, lParam); case TVN_SELCHANGING: return TRUE; case HDN_ENDTRACK: SendMessage(ptr->hwndTree, TCF_SETDIVIDER, 0, n->pitem->cxy); InvalidateRect(ptr->hwndTree, 0, 1); return 0; case TVN_GETDISPINFO: t = (LPNMTVDISPINFO)n; if (TreeView_GetItemRect(ptr->hwndTree, t->item.hItem, &r, TRUE) ) { if (ptr->displaycount < DISPLAY_MAX) ptr->displaylist[ptr->displaycount++] = t->item.hItem; strcpy(t->item.pszText, ""); // t->item.cchTextMax = 0; } return 0; case TVN_DELETEITEM: ntv = (NM_TREEVIEW*)lParam; if (ptr->displaycount) for (i = 0; i < ptr->displaycount; i++) if (ptr->displaylist[i] == ntv->itemOld.hItem) { ptr->sel = - 1; memcpy(&ptr->displaylist[i], &ptr->displaylist[i + 1], (ptr ->displaycount - i - 1) *sizeof(HTREEITEM)); ptr->displaycount--; return 0; } return 0; } // fall through case WM_COMMAND: return SendMessage(GetParent(hwnd), iMessage, wParam, lParam); case WM_CREATE: ptr = (COLUMNINFO*)calloc(1, sizeof(COLUMNINFO) ); ptr->displaycount = 0; ptr->sel = - 1; SetWindowLong(hwnd, 0, (int)ptr); GetClientRect(hwnd, &r); ptr->hwndHeader = CreateWindow(WC_HEADER, 0, WS_CLIPSIBLINGS | WS_CHILD | HDS_HORZ | WS_BORDER, r.left, r.top, r.right - r.left, r.bottom - r.top, hwnd, 0, (HINSTANCE)GetWindowLong (GetParent(hwnd), GWL_HINSTANCE), 0); hdl.prc = &r; hdl.pwpos = ℘ SendMessage(ptr->hwndHeader, HDM_LAYOUT, 0, (LPARAM) &hdl); // wp.x += 2*GetSystemMetrics(SM_CXDLGFRAME ); // wp.cx -= 4 * GetSystemMetrics(SM_CXDLGFRAME) ; // wp.y += 2*GetSystemMetrics(SM_CYDLGFRAME ); // wp.cy -= 4 * GetSystemMetrics(SM_CYDLGFRAME) ; ptr->watchFont = CreateFontIndirect(&systemDialogFont); SendMessage(ptr->hwndHeader, WM_SETFONT, (WPARAM)ptr->watchFont, 0); SetWindowPos(ptr->hwndHeader, wp.hwndInsertAfter, wp.x, wp.y, wp.cx, wp.cy, wp.flags | SWP_SHOWWINDOW); r.left = wp.x; r.right = wp.x + wp.cx; r.top = wp.y + wp.cy; ptr->hwndTree = CreateWindowEx(0, szextTreeWindClassName, 0, WS_CLIPSIBLINGS | WS_VISIBLE | WS_CHILD | WS_BORDER | TVS_HASLINES | TVS_LINESATROOT | TVS_HASBUTTONS, r.left, r.top, r.right - r.left, r.bottom - r.top, hwnd, (HMENU)1000, (HINSTANCE)GetWindowLong(GetParent(hwnd), GWL_HINSTANCE), 0); SendMessage(ptr->hwndTree, WM_SETFONT, (WPARAM)ptr->watchFont, 0); hie.mask = HDI_WIDTH; SendMessage(ptr->hwndHeader, HDM_GETITEM, 0, (LPARAM) &hie); SendMessage(ptr->hwndTree, TCF_SETDIVIDER, 0, hie.cxy); break; case WM_DESTROY: ptr = (COLUMNINFO*)GetWindowLong(hwnd, 0); DestroyWindow(ptr->hwndHeader); DeleteObject(ptr->watchFont); free((void*)ptr); break; case WM_LBUTTONDOWN: case WM_RBUTTONDOWN: break; case WM_SIZE: ptr = (COLUMNINFO*)GetWindowLong(hwnd, 0); r.left = r.top = 0; r.right = LOWORD(lParam); r.bottom = HIWORD(lParam); hdl.prc = &r; hdl.pwpos = ℘ SendMessage(ptr->hwndHeader, HDM_LAYOUT, 0, (LPARAM) &hdl); // wp.x += 2*GetSystemMetrics(SM_CXDLGFRAME ); // wp.cx -= 4 * GetSystemMetrics(SM_CXDLGFRAME) ; // wp.y += 2*GetSystemMetrics(SM_CYDLGFRAME ); // wp.cy -= 4 * GetSystemMetrics(SM_CYDLGFRAME) ; SetWindowPos(ptr->hwndHeader, wp.hwndInsertAfter, wp.x, wp.y, wp.cx, wp.cy, wp.flags); r.left = wp.x; r.right = wp.x + wp.cx; r.top = wp.y + wp.cy; MoveWindow(ptr->hwndTree, r.left, r.top, r.right - r.left, r.bottom - r.top, 0); GetClientRect(ptr->hwndHeader, &r); hie.mask = HDI_WIDTH; hie.cxy = (r.right - r.left) / 2; SendMessage(ptr->hwndHeader, HDM_SETITEM, 0, (LPARAM) &hie); SendMessage(ptr->hwndHeader, HDM_SETITEM, 1, (LPARAM) &hie); SendMessage(ptr->hwndTree, TCF_SETDIVIDER, 0, hie.cxy); InvalidateRect(ptr->hwndHeader, 0, 1); InvalidateRect(ptr->hwndTree, 0, 1); break; case TCF_SETHEADER: ptr = (COLUMNINFO*)GetWindowLong(hwnd, 0); h = (TCHeader*)lParam; GetWindowRect(ptr->hwndHeader, &r); hie.mask = HDI_TEXT | HDI_FORMAT | HDI_WIDTH; if (h->colBmp1) hie.mask |= HDI_BITMAP; hie.pszText = h->colText1; hie.hbm = h->colBmp1; hie.cxy = (r.right - r.left) / 2; hie.cchTextMax = strlen(h->colText1); hie.fmt = HDF_LEFT | HDF_STRING; SendMessage(ptr->hwndHeader, HDM_INSERTITEM, 100, (LPARAM) &hie); hie.mask = HDI_TEXT | HDI_FORMAT | HDI_WIDTH; if (h->colBmp2) hie.mask |= HDI_BITMAP; hie.pszText = h->colText2; hie.hbm = h->colBmp2; hie.cxy = (r.right - r.left) / 2; hie.cchTextMax = strlen(h->colText2); hie.fmt = HDF_LEFT | HDF_STRING; SendMessage(ptr->hwndHeader, HDM_INSERTITEM, 100, (LPARAM) &hie); SendMessage(ptr->hwndTree, TCF_SETDIVIDER, 0, hie.cxy); return 0; case WM_PAINT: dc = BeginPaint(hwnd, &ps); EndPaint(hwnd, &ps); break; case WM_ACTIVATEME: SendMessage(GetParent(hwnd), WM_ACTIVATEME, 0, 0); break; case WM_SETFONT: case WM_GETFONT: ptr = (COLUMNINFO*)GetWindowLong(hwnd, 0); return SendMessage(ptr->hwndTree, iMessage, wParam, lParam); case TCN_PAINT: rp = (RECT*)lParam; ptr = (COLUMNINFO*)GetWindowLong(hwnd, 0); { hie.mask = HDI_WIDTH; SendMessage(ptr->hwndHeader, HDM_GETITEM, 0, (LPARAM) &hie); hie.cxy -= GetSystemMetrics(SM_CXBORDER); rp->left = hie.cxy; if (rp->left < rp->right) { LOGBRUSH lbrush; HBRUSH graybrush; HDC dc = (HDC)wParam; int lined = FALSE; HFONT font = (HFONT)SendMessage(ptr->hwndTree, WM_GETFONT, 0, 0); lbrush.lbStyle = BS_SOLID; lbrush.lbColor = 0xff0000; graybrush = CreateBrushIndirect(&lbrush); // dc = GetDC(ptr->hwndTree); font = SelectObject(dc, font); if (GetWindowLong(hwnd, GWL_STYLE) &TCS_LINE) { HPEN pen; pen = CreatePen(PS_SOLID, 1, 0); lined = TRUE; pen = SelectObject(dc, pen); MoveToEx(dc, rp->left, rp->top, 0); LineTo(dc, rp->left, rp->bottom + 1); pen = SelectObject(dc, pen); DeleteObject(pen); } for (i = 0; i < ptr->displaycount; i++) { COLORREF color, bgcolor; item.hItem = ptr->displaylist[i]; item.mask = TVIF_PARAM; TreeView_GetItem(ptr->hwndTree, &item); td = (TCData*)item.lParam; TreeView_GetItemRect(ptr->hwndTree, ptr->displaylist[i], &r, TRUE); if (td->col1Text) { HRGN rgn; rgn = CreateRectRgn(r.left, r.top, rp->left - 2, r.bottom); SelectClipRgn(dc, rgn); if (ptr->sel == i) { color = SetTextColor(dc, RetrieveSysColor(COLOR_WINDOW)); bgcolor = SetBkColor(dc, td->col1Color); } else color = SetTextColor(dc, td->col1Color); TextOut(dc, r.left, r.top, td->col1Text, strlen(td ->col1Text)); SetTextColor(dc, color); if (ptr->sel == i) SetBkColor(dc, bgcolor); SelectClipRgn(dc, NULL); DeleteObject(rgn); } if (td->col2Text) { if (ptr->sel == i) { color = SetTextColor(dc, RetrieveSysColor(COLOR_WINDOW)); bgcolor = SetBkColor(dc, td->col2Color); } else color = SetTextColor(dc, td->col2Color); TextOut(dc, rp->left + (lined ? 3 : 0), r.top, td ->col2Text, strlen(td->col2Text)); SetTextColor(dc, color); if (ptr->sel == i) SetBkColor(dc, bgcolor); } } SelectObject(dc, font); // ReleaseDC(ptr->hwndTree, dc); DeleteObject(graybrush); } ptr->displaycount = 0; } break; } return DefWindowProc(hwnd, iMessage, wParam, lParam); }
LRESULT album_list_window::on_message(HWND wnd, UINT msg, WPARAM wp, LPARAM lp) { switch (msg) { case WM_CREATE: { list_wnd.add_item(this); initialised = true; modeless_dialog_manager::g_add(wnd); create_tree(); create_filter(); if (cfg_populate) refresh_tree(); static_api_ptr_t<library_manager_v3>()->register_callback(this); } break; /*case WM_GETMINMAXINFO: { LPMINMAXINFO mmi = LPMINMAXINFO(lp); mmi->ptMinTrackSize.y = cfg_height; return 0; }*/ case WM_SIZE: on_size(LOWORD(lp), HIWORD(lp)); break; /* case DM_GETDEFID: return (DC_HASDEFID<<16|IDOK); case WM_GETDLGCODE: return DLGC_DEFPUSHBUTTON;*/ // break; case WM_TIMER: if (wp == EDIT_TIMER_ID) { refresh_tree(); KillTimer(wnd, wp); m_timer = false; } break; case WM_COMMAND: switch (wp) { case IDC_FILTER | (EN_CHANGE << 16) : if (m_timer) KillTimer(wnd_edit, 500); m_timer = SetTimer(wnd, EDIT_TIMER_ID, 500, NULL) != 0; return TRUE; case IDOK: if (GetKeyState(VK_SHIFT) & KF_UP) do_playlist(p_selection, false); else if (GetKeyState(VK_CONTROL) & KF_UP) do_playlist(p_selection, true, true); else do_playlist(p_selection, true); return 0; } break; case WM_CONTEXTMENU: { enum { ID_SEND = 1, ID_ADD, ID_NEW, ID_AUTOSEND, ID_REMOVE, ID_REMOVEDEAD, ID_REFRESH, ID_FILT, ID_CONF, ID_VIEW_BASE }; HMENU menu = CreatePopupMenu(); POINT pt = { GET_X_LPARAM(lp), GET_Y_LPARAM(lp) }; service_ptr_t<contextmenu_manager> p_menu_manager; unsigned IDM_MANAGER_BASE = 0; HWND list = wnd_tv; HTREEITEM treeitem = NULL; TVHITTESTINFO ti; memset(&ti, 0, sizeof(ti)); if (pt.x != -1 && pt.y != -1) { ti.pt = pt; ScreenToClient(list, &ti.pt); uSendMessage(list, TVM_HITTEST, 0, (long)&ti); if (ti.hItem && (ti.flags & TVHT_ONITEM)) { //FIX THIS AND AUTOSEND //TreeView_Select(list, ti.hItem, TVGN_DROPHILITE); //uSendMessage(list,TVM_SELECTITEM,TVGN_DROPHILITE,(long)ti.hItem); treeitem = ti.hItem; } } else { treeitem = TreeView_GetSelection(list); RECT rc; if (treeitem && TreeView_GetItemRect(wnd_tv, treeitem, &rc, TRUE)) { MapWindowPoints(wnd_tv, HWND_DESKTOP, (LPPOINT)&rc, 2); pt.x = rc.left; pt.y = rc.top + (rc.bottom - rc.top) / 2; } else { GetMessagePos(&pt); } } TreeView_Select(list, treeitem, TVGN_DROPHILITE); HMENU menu_view = CreatePopupMenu(); unsigned n, m = cfg_view_list.get_count(); string8_fastalloc temp; temp.prealloc(32); uAppendMenu(menu_view, MF_STRING | (!stricmp_utf8(directory_structure_view_name, view) ? MF_CHECKED : 0), ID_VIEW_BASE + 0, directory_structure_view_name); list_t<string_simple, pfc::alloc_fast> views; views.add_item(string_simple(directory_structure_view_name)); for (n = 0; n<m; n++) { temp = cfg_view_list.get_name(n); string_simple item(temp.get_ptr()); if (item) { uAppendMenu(menu_view, MF_STRING | (!stricmp_utf8(temp, view) ? MF_CHECKED : 0), ID_VIEW_BASE + views.add_item(item), temp); } } IDM_MANAGER_BASE = ID_VIEW_BASE + views.get_count(); uAppendMenu(menu, MF_STRING | MF_POPUP, (UINT)menu_view, "View"); if (!m_populated && !cfg_populate) uAppendMenu(menu, MF_STRING, ID_REFRESH, "Populate"); uAppendMenu(menu, MF_STRING | (m_filter ? MF_CHECKED : 0), ID_FILT, "Filter"); uAppendMenu(menu, MF_STRING, ID_CONF, "Settings"); bool show_shortcuts = standard_config_objects::query_show_keyboard_shortcuts_in_menus(); node * p_node = NULL; TVITEMEX tvi; memset(&tvi, 0, sizeof(tvi)); tvi.hItem = treeitem; tvi.mask = TVIF_HANDLE | TVIF_PARAM; TreeView_GetItem(list, &tvi); p_node = (node*)tvi.lParam; if (treeitem && p_node) { uAppendMenu(menu, MF_SEPARATOR, 0, ""); uAppendMenu(menu, MF_STRING, ID_SEND, (show_shortcuts ? "&Send to playlist\tEnter" : "&Send to playlist")); uAppendMenu(menu, MF_STRING, ID_ADD, show_shortcuts ? "&Add to playlist\tShift+Enter" : "&Add to playlist"); uAppendMenu(menu, MF_STRING, ID_NEW, show_shortcuts ? "Send to &new playlist\tCtrl+Enter" : "Send to &new playlist"); uAppendMenu(menu, MF_STRING, ID_AUTOSEND, "Send to &autosend playlist"); if (!static_api_ptr_t<core_version_info_v2>()->test_version(0, 9, 6, 0)) { uAppendMenu(menu, MF_STRING, ID_REMOVE, "&Remove from library"); uAppendMenu(menu, MF_STRING, ID_REMOVEDEAD, "Remove &dead entries (slow)"); } uAppendMenu(menu, MF_SEPARATOR, 0, ""); contextmenu_manager::g_create(p_menu_manager); p_node->sort_entries(); if (p_menu_manager.is_valid()) { p_menu_manager->init_context(p_node->get_entries(), 0); p_menu_manager->win32_build_menu(menu, IDM_MANAGER_BASE, -1); menu_helpers::win32_auto_mnemonics(menu); } } int cmd = TrackPopupMenu(menu, TPM_RIGHTBUTTON | TPM_NONOTIFY | TPM_RETURNCMD, pt.x, pt.y, 0, get_wnd(), 0); DestroyMenu(menu); TreeView_Select(list, NULL, TVGN_DROPHILITE); if (cmd) { if (p_menu_manager.is_valid() && (unsigned)cmd >= IDM_MANAGER_BASE) { p_menu_manager->execute_by_id(cmd - IDM_MANAGER_BASE); } else if (cmd >= ID_VIEW_BASE) { unsigned n = cmd - ID_VIEW_BASE; if (n<views.get_count()) { view = views[n].get_ptr(); refresh_tree(); } } else if (cmd<ID_VIEW_BASE) { unsigned cmd2 = 0; switch (cmd) { case ID_NEW: do_playlist(p_node, true, true); break; case ID_SEND: do_playlist(p_node, true); break; case ID_ADD: do_playlist(p_node, false); break; case ID_AUTOSEND: do_autosend_playlist(p_node, view, true); break; case ID_CONF: { static_api_ptr_t<ui_control>()->show_preferences(g_guid_preferences_album_list_panel); } break; case ID_FILT: { m_filter = !m_filter; create_or_destroy_filter(); } break; case ID_REMOVE: p_node->remove_from_db(); break; case ID_REMOVEDEAD: p_node->remove_dead(); break; case ID_REFRESH: if (!m_populated && !cfg_populate) refresh_tree(); break; } if (cmd2) uSendMessage(get_wnd(), WM_COMMAND, cmd2, 0); } } p_menu_manager.release(); /* if (treeitem_context && (treeitem_context != treeitem) && cfg_autosend) TreeView_SelectItem(wnd_tv,treeitem);*/ } return 0; case WM_NOTIFY: { LPNMHDR hdr = (LPNMHDR)lp; switch (hdr->idFrom) { case IDC_TREE: { if (hdr->code == TVN_ITEMEXPANDING) { LPNMTREEVIEW param = (LPNMTREEVIEW)hdr; if (cfg_picmixer && (param->action == TVE_EXPAND)) { TreeView_CollapseOtherNodes(param->hdr.hwndFrom, param->itemNew.hItem); } } else if (hdr->code == TVN_SELCHANGED) { LPNMTREEVIEW param = (LPNMTREEVIEW)hdr; p_selection = (node*)param->itemNew.lParam; if ((param->action == TVC_BYMOUSE || param->action == TVC_BYKEYBOARD)) { if (cfg_autosend) do_autosend_playlist(p_selection, view); } if (m_selection_holder.is_valid()) { m_selection_holder->set_selection(p_selection.is_valid() ? p_selection->get_entries() : metadb_handle_list()); } #if 0 if (cfg_picmixer) { HTREEITEM ti_parent_old = TreeView_GetParent(param->hdr.hwndFrom, param->itemOld.hItem); HTREEITEM ti_parent_new = TreeView_GetParent(param->hdr.hwndFrom, param->itemNew.hItem); if (/*ti_parent_old != param->itemNew.hItem && */!TreeView_IsChild(param->hdr.hwndFrom, param->itemNew.hItem, param->itemOld.hItem)) { HTREEITEM ti = //TreeView_GetLevel(param->hdr.hwndFrom, param->itemNew.hItem) < TreeView_GetLevel(param->hdr.hwndFrom, param->itemOld.hItem) ? TreeView_GetCommonParentChild(param->hdr.hwndFrom, param->itemOld.hItem, param->itemNew.hItem) //: param->itemOld.hItem ; if (ti && ti != TVI_ROOT) TreeView_Expand(param->hdr.hwndFrom, ti, TVE_COLLAPSE); } if (ti_parent_new) { HTREEITEM child = TreeView_GetChild(param->hdr.hwndFrom, ti_parent_new); while (child) { if (child != param->itemNew.hItem) { } } } } #endif } } break; } } break; case WM_DESTROY: static_api_ptr_t<library_manager_v3>()->unregister_callback(this); modeless_dialog_manager::g_remove(wnd); destroy_tree(); destroy_filter(); m_selection_holder.release(); m_root.release(); p_selection.release(); if (initialised) { list_wnd.remove_item(this); if (list_wnd.get_count() == 0) { DeleteFont(g_font); g_font = 0; } initialised = false; } break; } return DefWindowProc(wnd, msg, wp, lp); }