4 * Copyright (C) 2002 Robert Dickenson <robd@reactos.org>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 ChildWnd
* g_pChildWnd
;
24 static int last_split
;
25 HBITMAP SizingPattern
= 0;
26 HBRUSH SizingBrush
= 0;
27 static TCHAR Suggestions
[256];
29 /*******************************************************************************
30 * Local module support methods
33 static LPCTSTR
get_root_key_name(HKEY hRootKey
)
35 if (hRootKey
== HKEY_CLASSES_ROOT
) return _T("HKEY_CLASSES_ROOT");
36 if (hRootKey
== HKEY_CURRENT_USER
) return _T("HKEY_CURRENT_USER");
37 if (hRootKey
== HKEY_LOCAL_MACHINE
) return _T("HKEY_LOCAL_MACHINE");
38 if (hRootKey
== HKEY_USERS
) return _T("HKEY_USERS");
39 if (hRootKey
== HKEY_CURRENT_CONFIG
) return _T("HKEY_CURRENT_CONFIG");
40 if (hRootKey
== HKEY_DYN_DATA
) return _T("HKEY_DYN_DATA");
41 return _T("UKNOWN HKEY, PLEASE REPORT");
44 static void draw_splitbar(HWND hWnd
, int x
)
48 HDC hdc
= GetDC(hWnd
);
52 const DWORD Pattern
[4] = {0x5555AAAA, 0x5555AAAA, 0x5555AAAA, 0x5555AAAA};
53 SizingPattern
= CreateBitmap(8, 8, 1, 1, Pattern
);
57 SizingBrush
= CreatePatternBrush(SizingPattern
);
59 GetClientRect(hWnd
, &rt
);
60 rt
.left
= x
- SPLIT_WIDTH
/2;
61 rt
.right
= x
+ SPLIT_WIDTH
/2+1;
62 OldObj
= SelectObject(hdc
, SizingBrush
);
63 PatBlt(hdc
, rt
.left
, rt
.top
, rt
.right
- rt
.left
, rt
.bottom
- rt
.top
, PATINVERT
);
64 SelectObject(hdc
, OldObj
);
68 static void ResizeWnd(ChildWnd
* pChildWnd
, int cx
, int cy
)
70 HDWP hdwp
= BeginDeferWindowPos(2);
73 SetRect(&rt
, 0, 0, cx
, cy
);
75 if (hStatusBar
!= NULL
) {
76 GetWindowRect(hStatusBar
, &rs
);
77 cy
= rs
.bottom
- rs
.top
+ 8;
79 cx
= pChildWnd
->nSplitPos
+ SPLIT_WIDTH
/2;
80 DeferWindowPos(hdwp
, pChildWnd
->hAddressBarWnd
, 0, rt
.left
, rt
.top
, rt
.right
-rt
.left
, 23, SWP_NOZORDER
|SWP_NOACTIVATE
);
81 DeferWindowPos(hdwp
, pChildWnd
->hTreeWnd
, 0, rt
.left
, rt
.top
+ 25, pChildWnd
->nSplitPos
-SPLIT_WIDTH
/2-rt
.left
, rt
.bottom
-rt
.top
-cy
, SWP_NOZORDER
|SWP_NOACTIVATE
);
82 DeferWindowPos(hdwp
, pChildWnd
->hListWnd
, 0, rt
.left
+cx
, rt
.top
+ 25, rt
.right
-cx
, rt
.bottom
-rt
.top
-cy
, SWP_NOZORDER
|SWP_NOACTIVATE
);
83 EndDeferWindowPos(hdwp
);
86 static void OnPaint(HWND hWnd
)
91 GetClientRect(hWnd
, &rt
);
92 BeginPaint(hWnd
, &ps
);
93 FillRect(ps
.hdc
, &rt
, GetSysColorBrush(COLOR_BTNFACE
));
97 /*******************************************************************************
98 * finish_splitbar [internal]
100 * make the splitbar invisible and resize the windows
101 * (helper for ChildWndProc)
103 static void finish_splitbar(HWND hWnd
, int x
)
107 draw_splitbar(hWnd
, last_split
);
109 GetClientRect(hWnd
, &rt
);
110 g_pChildWnd
->nSplitPos
= x
;
111 ResizeWnd(g_pChildWnd
, rt
.right
, rt
.bottom
);
115 /*******************************************************************************
117 * FUNCTION: _CmdWndProc(HWND, unsigned, WORD, LONG)
119 * PURPOSE: Processes WM_COMMAND messages for the main frame window.
123 static BOOL
_CmdWndProc(HWND hWnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
125 ChildWnd
* pChildWnd
= g_pChildWnd
;
126 HTREEITEM hSelection
;
129 WORD wID
= LOWORD(wParam
);
131 UNREFERENCED_PARAMETER(message
);
134 /* Parse the menu selections: */
135 case ID_REGISTRY_EXIT
:
138 case ID_VIEW_REFRESH
:
141 case ID_TREE_EXPANDBRANCH
:
142 (void)TreeView_Expand(pChildWnd
->hTreeWnd
, TreeView_GetSelection(pChildWnd
->hTreeWnd
), TVE_EXPAND
);
144 case ID_TREE_COLLAPSEBRANCH
:
145 (void)TreeView_Expand(pChildWnd
->hTreeWnd
, TreeView_GetSelection(pChildWnd
->hTreeWnd
), TVE_COLLAPSE
);
148 SetFocus(pChildWnd
->hTreeWnd
);
149 (void)TreeView_EditLabel(pChildWnd
->hTreeWnd
, TreeView_GetSelection(pChildWnd
->hTreeWnd
));
152 hSelection
= TreeView_GetSelection(pChildWnd
->hTreeWnd
);
153 keyPath
= GetItemPath(pChildWnd
->hTreeWnd
, hSelection
, &hRootKey
);
155 if (keyPath
== 0 || *keyPath
== 0)
157 MessageBeep(MB_ICONHAND
);
159 if (DeleteKey(hWnd
, hRootKey
, keyPath
))
160 DeleteNode(g_pChildWnd
->hTreeWnd
, 0);
163 ExportRegistryFile(pChildWnd
->hTreeWnd
);
168 case ID_EDIT_COPYKEYNAME
:
169 hSelection
= TreeView_GetSelection(pChildWnd
->hTreeWnd
);
170 keyPath
= GetItemPath(pChildWnd
->hTreeWnd
, hSelection
, &hRootKey
);
171 CopyKeyName(hWnd
, hRootKey
, keyPath
);
173 case ID_EDIT_NEW_KEY
:
174 CreateNewKey(pChildWnd
->hTreeWnd
, TreeView_GetSelection(pChildWnd
->hTreeWnd
));
176 case ID_EDIT_NEW_STRINGVALUE
:
177 case ID_EDIT_NEW_BINARYVALUE
:
178 case ID_EDIT_NEW_DWORDVALUE
:
179 SendMessage(hFrameWnd
, WM_COMMAND
, wParam
, lParam
);
181 case ID_SWITCH_PANELS
:
182 pChildWnd
->nFocusPanel
= !pChildWnd
->nFocusPanel
;
183 SetFocus(pChildWnd
->nFocusPanel
? pChildWnd
->hListWnd
: pChildWnd
->hTreeWnd
);
186 if ((wID
>= ID_TREE_SUGGESTION_MIN
) && (wID
<= ID_TREE_SUGGESTION_MAX
))
189 while(wID
> ID_TREE_SUGGESTION_MIN
)
195 SelectNode(pChildWnd
->hTreeWnd
, s
);
203 /*******************************************************************************
208 #define MIN(a,b) ((a < b) ? (a) : (b))
210 static void SuggestKeys(HKEY hRootKey
, LPCTSTR pszKeyPath
, LPTSTR pszSuggestions
,
211 size_t iSuggestionsLength
)
214 TCHAR szLastFound
[256];
216 HKEY hOtherKey
, hSubKey
;
219 memset(pszSuggestions
, 0, iSuggestionsLength
* sizeof(*pszSuggestions
));
220 iSuggestionsLength
--;
222 /* Are we a root key in HKEY_CLASSES_ROOT? */
223 if ((hRootKey
== HKEY_CLASSES_ROOT
) && pszKeyPath
[0] && !_tcschr(pszKeyPath
, TEXT('\\')))
229 /* Check default key */
230 if (QueryStringValue(hRootKey
, pszKeyPath
, NULL
,
231 szBuffer
, COUNT_OF(szBuffer
)) == ERROR_SUCCESS
)
233 /* Sanity check this key; it cannot be empty, nor can it be a
235 if ((szBuffer
[0] != '\0') && _tcsicmp(szBuffer
, pszKeyPath
))
237 if (RegOpenKey(hRootKey
, szBuffer
, &hOtherKey
) == ERROR_SUCCESS
)
239 lstrcpyn(pszSuggestions
, TEXT("HKCR\\"), (int) iSuggestionsLength
);
240 i
= _tcslen(pszSuggestions
);
242 iSuggestionsLength
-= i
;
244 lstrcpyn(pszSuggestions
, szBuffer
, (int) iSuggestionsLength
);
245 i
= MIN(_tcslen(pszSuggestions
) + 1, iSuggestionsLength
);
247 iSuggestionsLength
-= i
;
248 RegCloseKey(hOtherKey
);
251 _tcscpy(szLastFound
, szBuffer
);
252 pszKeyPath
= szLastFound
;
257 while(bFound
&& (iSuggestionsLength
> 0));
259 /* Check CLSID key */
260 if (RegOpenKey(hRootKey
, pszKeyPath
, &hSubKey
) == ERROR_SUCCESS
)
262 if (QueryStringValue(hSubKey
, TEXT("CLSID"), NULL
, szBuffer
,
263 COUNT_OF(szBuffer
)) == ERROR_SUCCESS
)
265 lstrcpyn(pszSuggestions
, TEXT("HKCR\\CLSID\\"), (int) iSuggestionsLength
);
266 i
= _tcslen(pszSuggestions
);
268 iSuggestionsLength
-= i
;
270 lstrcpyn(pszSuggestions
, szBuffer
, (int) iSuggestionsLength
);
271 i
= MIN(_tcslen(pszSuggestions
) + 1, iSuggestionsLength
);
273 iSuggestionsLength
-= i
;
275 RegCloseKey(hSubKey
);
281 LRESULT CALLBACK
AddressBarProc(HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
284 static TCHAR s_szNode
[256];
285 oldwndproc
= (WNDPROC
)(LONG_PTR
)GetWindowLongPtr(hwnd
, GWL_USERDATA
);
290 if (wParam
== VK_RETURN
)
292 GetWindowText(hwnd
, s_szNode
, sizeof(s_szNode
) / sizeof(s_szNode
[0]));
293 SelectNode(g_pChildWnd
->hTreeWnd
, s_szNode
);
299 return CallWindowProc(oldwndproc
, hwnd
, uMsg
, wParam
, lParam
);
302 /*******************************************************************************
304 * FUNCTION: ChildWndProc(HWND, unsigned, WORD, LONG)
306 * PURPOSE: Processes messages for the child windows.
308 * WM_COMMAND - process the application menu
309 * WM_PAINT - Paint the main window
310 * WM_DESTROY - post a quit message and return
313 LRESULT CALLBACK
ChildWndProc(HWND hWnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
316 ChildWnd
* pChildWnd
= g_pChildWnd
;
323 TCHAR buffer
[MAX_PATH
];
324 /* load "My Computer" string */
325 LoadString(hInst
, IDS_MY_COMPUTER
, buffer
, sizeof(buffer
)/sizeof(TCHAR
));
327 g_pChildWnd
= pChildWnd
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(ChildWnd
));
329 if (!pChildWnd
) return 0;
330 _tcsncpy(pChildWnd
->szPath
, buffer
, MAX_PATH
);
331 pChildWnd
->nSplitPos
= 250;
332 pChildWnd
->hWnd
= hWnd
;
333 pChildWnd
->hAddressBarWnd
= CreateWindowEx(WS_EX_CLIENTEDGE
, _T("Edit"), NULL
, WS_CHILD
| WS_VISIBLE
| WS_CHILDWINDOW
| WS_TABSTOP
,
334 CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
,
335 hWnd
, (HMENU
)0, hInst
, 0);
336 pChildWnd
->hTreeWnd
= CreateTreeView(hWnd
, pChildWnd
->szPath
, (HMENU
) TREE_WINDOW
);
337 pChildWnd
->hListWnd
= CreateListView(hWnd
, (HMENU
) LIST_WINDOW
/*, pChildWnd->szPath*/);
338 SetFocus(pChildWnd
->hTreeWnd
);
340 /* set the address bar font */
341 if (pChildWnd
->hAddressBarWnd
)
343 hFont
= (HFONT
)GetStockObject(DEFAULT_GUI_FONT
);
344 SendMessage(pChildWnd
->hAddressBarWnd
,
350 /* Subclass the AddressBar */
351 oldproc
= (WNDPROC
)(LONG_PTR
)GetWindowLongPtr(pChildWnd
->hAddressBarWnd
, GWL_WNDPROC
);
352 SetWindowLongPtr(pChildWnd
->hAddressBarWnd
, GWL_USERDATA
, (DWORD_PTR
)oldproc
);
353 SetWindowLongPtr(pChildWnd
->hAddressBarWnd
, GWL_WNDPROC
, (DWORD_PTR
)AddressBarProc
);
357 if (!_CmdWndProc(hWnd
, message
, wParam
, lParam
)) {
365 if (LOWORD(lParam
) == HTCLIENT
) {
368 ScreenToClient(hWnd
, &pt
);
369 if (pt
.x
>=pChildWnd
->nSplitPos
-SPLIT_WIDTH
/2 && pt
.x
<pChildWnd
->nSplitPos
+SPLIT_WIDTH
/2+1) {
370 SetCursor(LoadCursor(0, IDC_SIZEWE
));
377 DestroyListView(pChildWnd
->hListWnd
);
379 HeapFree(GetProcessHeap(), 0, pChildWnd
);
383 case WM_LBUTTONDOWN
: {
385 int x
= (short)LOWORD(lParam
);
386 GetClientRect(hWnd
, &rt
);
387 if (x
>=pChildWnd
->nSplitPos
-SPLIT_WIDTH
/2 && x
<pChildWnd
->nSplitPos
+SPLIT_WIDTH
/2+1) {
388 last_split
= pChildWnd
->nSplitPos
;
389 draw_splitbar(hWnd
, last_split
);
397 if (GetCapture() == hWnd
) {
398 finish_splitbar(hWnd
, LOWORD(lParam
));
402 case WM_CAPTURECHANGED
:
403 if (GetCapture()==hWnd
&& last_split
>=0)
404 draw_splitbar(hWnd
, last_split
);
408 if (wParam
== VK_ESCAPE
)
409 if (GetCapture() == hWnd
) {
411 draw_splitbar(hWnd
, last_split
);
412 GetClientRect(hWnd
, &rt
);
413 ResizeWnd(pChildWnd
, rt
.right
, rt
.bottom
);
416 SetCursor(LoadCursor(0, IDC_ARROW
));
421 if (GetCapture() == hWnd
) {
425 int x
= LOWORD(lParam
);
428 const DWORD Pattern
[4] = {0x5555AAAA, 0x5555AAAA, 0x5555AAAA, 0x5555AAAA};
429 SizingPattern
= CreateBitmap(8, 8, 1, 1, Pattern
);
433 SizingBrush
= CreatePatternBrush(SizingPattern
);
436 GetClientRect(hWnd
, &rt
);
437 x
= (SHORT
) min(max(x
, SPLIT_MIN
), rt
.right
- SPLIT_MIN
);
440 rt
.left
= last_split
-SPLIT_WIDTH
/2;
441 rt
.right
= last_split
+SPLIT_WIDTH
/2+1;
443 OldObj
= SelectObject(hdc
, SizingBrush
);
444 PatBlt(hdc
, rt
.left
, rt
.top
, rt
.right
- rt
.left
, rt
.bottom
- rt
.top
, PATINVERT
);
446 rt
.left
= x
-SPLIT_WIDTH
/2;
447 rt
.right
= x
+SPLIT_WIDTH
/2+1;
448 PatBlt(hdc
, rt
.left
, rt
.top
, rt
.right
- rt
.left
, rt
.bottom
- rt
.top
, PATINVERT
);
449 SelectObject(hdc
, OldObj
);
450 ReleaseDC(hWnd
, hdc
);
456 if (pChildWnd
!= NULL
) {
457 SetFocus(pChildWnd
->nFocusPanel
? pChildWnd
->hListWnd
: pChildWnd
->hTreeWnd
);
465 if ((int)wParam
== TREE_WINDOW
) {
466 switch (((LPNMHDR
)lParam
)->code
) {
467 case TVN_ITEMEXPANDING
:
468 return !OnTreeExpanding(pChildWnd
->hTreeWnd
, (NMTREEVIEW
*)lParam
);
469 case TVN_SELCHANGED
: {
470 LPCTSTR keyPath
, rootName
;
474 keyPath
= GetItemPath(pChildWnd
->hTreeWnd
, ((NMTREEVIEW
*)lParam
)->itemNew
.hItem
, &hRootKey
);
476 RefreshListView(pChildWnd
->hListWnd
, hRootKey
, keyPath
);
477 rootName
= get_root_key_name(hRootKey
);
478 fullPath
= HeapAlloc(GetProcessHeap(), 0, (_tcslen(rootName
) + 1 + _tcslen(keyPath
) + 1) * sizeof(TCHAR
));
480 _stprintf(fullPath
, _T("%s\\%s"), rootName
, keyPath
);
481 SendMessage(hStatusBar
, SB_SETTEXT
, 0, (LPARAM
)fullPath
);
482 SendMessage(pChildWnd
->hAddressBarWnd
, WM_SETTEXT
, 0, (LPARAM
)fullPath
);
483 HeapFree(GetProcessHeap(), 0, fullPath
);
487 TCHAR szBuffer
[MAX_PATH
];
488 _sntprintf(szBuffer
, sizeof(szBuffer
) / sizeof(szBuffer
[0]), _T("My Computer\\%s\\%s"), rootName
, keyPath
);
490 if (RegCreateKey(HKEY_CURRENT_USER
,
492 &hKey
) == ERROR_SUCCESS
)
494 RegSetValueEx(hKey
, _T("LastKey"), 0, REG_SZ
, (LPBYTE
) szBuffer
, (DWORD
) _tcslen(szBuffer
) * sizeof(szBuffer
[0]));
503 pChildWnd
->nFocusPanel
= 0;
505 case TVN_BEGINLABELEDIT
:
507 LPNMTVDISPINFO ptvdi
;
508 /* cancel label edit for rootkeys */
509 ptvdi
= (LPNMTVDISPINFO
) lParam
;
510 if (!TreeView_GetParent(pChildWnd
->hTreeWnd
, ptvdi
->item
.hItem
) ||
511 !TreeView_GetParent(pChildWnd
->hTreeWnd
, TreeView_GetParent(pChildWnd
->hTreeWnd
, ptvdi
->item
.hItem
)))
515 case TVN_ENDLABELEDIT
:
520 LPNMTVDISPINFO ptvdi
;
522 TCHAR szBuffer
[MAX_PATH
];
524 ptvdi
= (LPNMTVDISPINFO
) lParam
;
525 if (ptvdi
->item
.pszText
)
527 keyPath
= GetItemPath(pChildWnd
->hTreeWnd
, TreeView_GetParent(pChildWnd
->hTreeWnd
, ptvdi
->item
.hItem
), &hRootKey
);
528 _sntprintf(szBuffer
, sizeof(szBuffer
) / sizeof(szBuffer
[0]), _T("%s\\%s"), keyPath
, ptvdi
->item
.pszText
);
529 keyPath
= GetItemPath(pChildWnd
->hTreeWnd
, ptvdi
->item
.hItem
, &hRootKey
);
530 if (RegOpenKeyEx(hRootKey
, szBuffer
, 0, KEY_READ
, &hKey
) == ERROR_SUCCESS
)
534 (void)TreeView_EditLabel(pChildWnd
->hTreeWnd
, ptvdi
->item
.hItem
);
538 if (RenameKey(hRootKey
, keyPath
, ptvdi
->item
.pszText
) != ERROR_SUCCESS
)
549 if ((int)wParam
== LIST_WINDOW
)
551 switch (((LPNMHDR
)lParam
)->code
) {
553 pChildWnd
->nFocusPanel
= 1;
556 if(!ListWndNotifyProc(pChildWnd
->hListWnd
, wParam
, lParam
, &Result
))
570 if((HWND
)wParam
== pChildWnd
->hListWnd
)
574 pt
.x
= (short) LOWORD(lParam
);
575 pt
.y
= (short) HIWORD(lParam
);
576 cnt
= ListView_GetSelectedCount(pChildWnd
->hListWnd
);
577 i
= ListView_GetNextItem(pChildWnd
->hListWnd
, -1, LVNI_FOCUSED
| LVNI_SELECTED
);
578 if (pt
.x
== -1 && pt
.y
== -1)
583 rc
.left
= LVIR_BOUNDS
;
584 SendMessage(pChildWnd
->hListWnd
, LVM_GETITEMRECT
, i
, (LPARAM
) &rc
);
590 ClientToScreen(pChildWnd
->hListWnd
, &pt
);
594 TrackPopupMenu(GetSubMenu(hPopupMenus
, PM_NEW
), TPM_RIGHTBUTTON
, pt
.x
, pt
.y
, 0, hFrameWnd
, NULL
);
598 HMENU mnu
= GetSubMenu(hPopupMenus
, PM_MODIFYVALUE
);
599 SetMenuDefaultItem(mnu
, ID_EDIT_MODIFY
, MF_BYCOMMAND
);
600 IsDefault
= IsDefaultValue(pChildWnd
->hListWnd
, i
);
602 EnableMenuItem(mnu
, ID_EDIT_RENAME
, MF_BYCOMMAND
| (IsDefault
? MF_DISABLED
| MF_GRAYED
: MF_ENABLED
));
604 EnableMenuItem(mnu
, ID_EDIT_RENAME
, MF_BYCOMMAND
| MF_DISABLED
| MF_GRAYED
);
605 EnableMenuItem(mnu
, ID_EDIT_MODIFY
, MF_BYCOMMAND
| (cnt
== 1 ? MF_ENABLED
: MF_DISABLED
| MF_GRAYED
));
606 EnableMenuItem(mnu
, ID_EDIT_MODIFY_BIN
, MF_BYCOMMAND
| (cnt
== 1 ? MF_ENABLED
: MF_DISABLED
| MF_GRAYED
));
608 TrackPopupMenu(mnu
, TPM_RIGHTBUTTON
, pt
.x
, pt
.y
, 0, hFrameWnd
, NULL
);
611 else if ((HWND
)wParam
== pChildWnd
->hTreeWnd
)
625 pt
.x
= (short) LOWORD(lParam
);
626 pt
.y
= (short) HIWORD(lParam
);
628 if (pt
.x
== -1 && pt
.y
== -1)
631 hti
.hItem
= TreeView_GetSelection(pChildWnd
->hTreeWnd
);
632 if (hti
.hItem
!= NULL
)
634 TreeView_GetItemRect(pChildWnd
->hTreeWnd
, hti
.hItem
, &rc
, TRUE
);
637 ClientToScreen(pChildWnd
->hTreeWnd
, &pt
);
638 hti
.flags
= TVHT_ONITEM
;
647 ScreenToClient(pChildWnd
->hTreeWnd
, &hti
.pt
);
648 (void)TreeView_HitTest(pChildWnd
->hTreeWnd
, &hti
);
651 if (hti
.flags
& TVHT_ONITEM
)
653 hContextMenu
= GetSubMenu(hPopupMenus
, PM_TREECONTEXT
);
654 (void)TreeView_SelectItem(pChildWnd
->hTreeWnd
, hti
.hItem
);
656 memset(&item
, 0, sizeof(item
));
657 item
.mask
= TVIF_STATE
| TVIF_CHILDREN
;
658 item
.hItem
= hti
.hItem
;
659 (void)TreeView_GetItem(pChildWnd
->hTreeWnd
, &item
);
661 /* Set the Expand/Collapse menu item appropriately */
662 LoadString(hInst
, (item
.state
& TVIS_EXPANDED
) ? IDS_COLLAPSE
: IDS_EXPAND
, buffer
, sizeof(buffer
) / sizeof(buffer
[0]));
663 memset(&mii
, 0, sizeof(mii
));
664 mii
.cbSize
= sizeof(mii
);
665 mii
.fMask
= MIIM_STRING
| MIIM_STATE
| MIIM_ID
;
666 mii
.fState
= (item
.cChildren
> 0) ? MFS_DEFAULT
: MFS_GRAYED
;
667 mii
.wID
= (item
.state
& TVIS_EXPANDED
) ? ID_TREE_COLLAPSEBRANCH
: ID_TREE_EXPANDBRANCH
;
668 mii
.dwTypeData
= (LPTSTR
) buffer
;
669 SetMenuItemInfo(hContextMenu
, 0, TRUE
, &mii
);
671 /* Remove any existing suggestions */
672 memset(&mii
, 0, sizeof(mii
));
673 mii
.cbSize
= sizeof(mii
);
675 GetMenuItemInfo(hContextMenu
, GetMenuItemCount(hContextMenu
) - 1, TRUE
, &mii
);
676 if ((mii
.wID
>= ID_TREE_SUGGESTION_MIN
) && (mii
.wID
<= ID_TREE_SUGGESTION_MAX
))
680 iLastPos
= GetMenuItemCount(hContextMenu
) - 1;
681 GetMenuItemInfo(hContextMenu
, iLastPos
, TRUE
, &mii
);
682 RemoveMenu(hContextMenu
, iLastPos
, MF_BYPOSITION
);
684 while((mii
.wID
>= ID_TREE_SUGGESTION_MIN
) && (mii
.wID
<= ID_TREE_SUGGESTION_MAX
));
687 /* Come up with suggestions */
688 keyPath
= GetItemPath(pChildWnd
->hTreeWnd
, NULL
, &hRootKey
);
689 SuggestKeys(hRootKey
, keyPath
, Suggestions
, sizeof(Suggestions
) / sizeof(Suggestions
[0]));
692 AppendMenu(hContextMenu
, MF_SEPARATOR
, 0, NULL
);
694 LoadString(hInst
, IDS_GOTO_SUGGESTED_KEY
, resource
, sizeof(resource
) / sizeof(resource
[0]));
697 wID
= ID_TREE_SUGGESTION_MIN
;
698 while(*s
&& (wID
<= ID_TREE_SUGGESTION_MAX
))
700 _sntprintf(buffer
, sizeof(buffer
) / sizeof(buffer
[0]), resource
, s
);
702 memset(&mii
, 0, sizeof(mii
));
703 mii
.cbSize
= sizeof(mii
);
704 mii
.fMask
= MIIM_STRING
| MIIM_ID
;
706 mii
.dwTypeData
= buffer
;
707 InsertMenuItem(hContextMenu
, GetMenuItemCount(hContextMenu
), TRUE
, &mii
);
712 TrackPopupMenu(hContextMenu
, TPM_RIGHTBUTTON
, pt
.x
, pt
.y
, 0, pChildWnd
->hWnd
, NULL
);
719 if (wParam
!= SIZE_MINIMIZED
&& pChildWnd
!= NULL
) {
720 ResizeWnd(pChildWnd
, LOWORD(lParam
), HIWORD(lParam
));
724 return DefWindowProc(hWnd
, message
, wParam
, lParam
);