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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 ChildWnd
* g_pChildWnd
;
24 HBITMAP SizingPattern
= 0;
25 HBRUSH SizingBrush
= 0;
26 static TCHAR Suggestions
[256];
28 /*******************************************************************************
29 * Local module support methods
32 static LPCTSTR
get_root_key_name(HKEY hRootKey
)
34 if (hRootKey
== HKEY_CLASSES_ROOT
) return _T("HKEY_CLASSES_ROOT");
35 if (hRootKey
== HKEY_CURRENT_USER
) return _T("HKEY_CURRENT_USER");
36 if (hRootKey
== HKEY_LOCAL_MACHINE
) return _T("HKEY_LOCAL_MACHINE");
37 if (hRootKey
== HKEY_USERS
) return _T("HKEY_USERS");
38 if (hRootKey
== HKEY_CURRENT_CONFIG
) return _T("HKEY_CURRENT_CONFIG");
39 if (hRootKey
== HKEY_DYN_DATA
) return _T("HKEY_DYN_DATA");
40 return _T("UKNOWN HKEY, PLEASE REPORT");
43 static void draw_splitbar(HWND hWnd
, int x
)
47 HDC hdc
= GetDC(hWnd
);
51 const DWORD Pattern
[4] = {0x5555AAAA, 0x5555AAAA, 0x5555AAAA, 0x5555AAAA};
52 SizingPattern
= CreateBitmap(8, 8, 1, 1, Pattern
);
56 SizingBrush
= CreatePatternBrush(SizingPattern
);
58 GetClientRect(hWnd
, &rt
);
59 rt
.left
= x
- SPLIT_WIDTH
/2;
60 rt
.right
= x
+ SPLIT_WIDTH
/2+1;
61 OldObj
= SelectObject(hdc
, SizingBrush
);
62 PatBlt(hdc
, rt
.left
, rt
.top
, rt
.right
- rt
.left
, rt
.bottom
- rt
.top
, PATINVERT
);
63 SelectObject(hdc
, OldObj
);
67 static void ResizeWnd(ChildWnd
* pChildWnd
, int cx
, int cy
)
69 HDWP hdwp
= BeginDeferWindowPos(2);
72 SetRect(&rt
, 0, 0, cx
, cy
);
74 if (hStatusBar
!= NULL
) {
75 GetWindowRect(hStatusBar
, &rs
);
76 cy
= rs
.bottom
- rs
.top
+ 8;
78 cx
= pChildWnd
->nSplitPos
+ SPLIT_WIDTH
/2;
79 DeferWindowPos(hdwp
, pChildWnd
->hAddressBarWnd
, 0, rt
.left
, rt
.top
, rt
.right
-rt
.left
, 23, SWP_NOZORDER
|SWP_NOACTIVATE
);
80 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
);
81 DeferWindowPos(hdwp
, pChildWnd
->hListWnd
, 0, rt
.left
+cx
, rt
.top
+ 25, rt
.right
-cx
, rt
.bottom
-rt
.top
-cy
, SWP_NOZORDER
|SWP_NOACTIVATE
);
82 EndDeferWindowPos(hdwp
);
85 static void OnPaint(HWND hWnd
)
91 GetClientRect(hWnd
, &rt
);
92 hdc
= BeginPaint(hWnd
, &ps
);
93 FillRect(ps
.hdc
, &rt
, GetSysColorBrush(COLOR_BTNFACE
));
97 /*******************************************************************************
99 * FUNCTION: _CmdWndProc(HWND, unsigned, WORD, LONG)
101 * PURPOSE: Processes WM_COMMAND messages for the main frame window.
105 static BOOL
_CmdWndProc(HWND hWnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
107 ChildWnd
* pChildWnd
= g_pChildWnd
;
108 HTREEITEM hSelection
;
111 WORD wID
= LOWORD(wParam
);
113 UNREFERENCED_PARAMETER(message
);
116 /* Parse the menu selections: */
117 case ID_REGISTRY_EXIT
:
120 case ID_VIEW_REFRESH
:
123 case ID_TREE_EXPANDBRANCH
:
124 (void)TreeView_Expand(pChildWnd
->hTreeWnd
, TreeView_GetSelection(pChildWnd
->hTreeWnd
), TVE_EXPAND
);
126 case ID_TREE_COLLAPSEBRANCH
:
127 (void)TreeView_Expand(pChildWnd
->hTreeWnd
, TreeView_GetSelection(pChildWnd
->hTreeWnd
), TVE_COLLAPSE
);
130 SetFocus(pChildWnd
->hTreeWnd
);
131 (void)TreeView_EditLabel(pChildWnd
->hTreeWnd
, TreeView_GetSelection(pChildWnd
->hTreeWnd
));
134 hSelection
= TreeView_GetSelection(pChildWnd
->hTreeWnd
);
135 keyPath
= GetItemPath(pChildWnd
->hTreeWnd
, hSelection
, &hRootKey
);
137 if (keyPath
== 0 || *keyPath
== 0)
139 MessageBeep(MB_ICONHAND
);
141 if (DeleteKey(hWnd
, hRootKey
, keyPath
))
142 DeleteNode(g_pChildWnd
->hTreeWnd
, 0);
145 ExportRegistryFile(pChildWnd
->hTreeWnd
);
150 case ID_EDIT_COPYKEYNAME
:
151 hSelection
= TreeView_GetSelection(pChildWnd
->hTreeWnd
);
152 keyPath
= GetItemPath(pChildWnd
->hTreeWnd
, hSelection
, &hRootKey
);
153 CopyKeyName(hWnd
, hRootKey
, keyPath
);
155 case ID_EDIT_NEW_KEY
:
156 CreateNewKey(pChildWnd
->hTreeWnd
, TreeView_GetSelection(pChildWnd
->hTreeWnd
));
158 case ID_EDIT_NEW_STRINGVALUE
:
159 case ID_EDIT_NEW_BINARYVALUE
:
160 case ID_EDIT_NEW_DWORDVALUE
:
161 SendMessage(hFrameWnd
, WM_COMMAND
, wParam
, lParam
);
163 case ID_SWITCH_PANELS
:
164 pChildWnd
->nFocusPanel
= !pChildWnd
->nFocusPanel
;
165 SetFocus(pChildWnd
->nFocusPanel
? pChildWnd
->hListWnd
: pChildWnd
->hTreeWnd
);
168 if ((wID
>= ID_TREE_SUGGESTION_MIN
) && (wID
<= ID_TREE_SUGGESTION_MAX
))
171 while(wID
> ID_TREE_SUGGESTION_MIN
)
177 SelectNode(pChildWnd
->hTreeWnd
, s
);
185 /*******************************************************************************
190 #define MIN(a,b) ((a < b) ? (a) : (b))
192 static void SuggestKeys(HKEY hRootKey
, LPCTSTR pszKeyPath
, LPTSTR pszSuggestions
,
193 size_t iSuggestionsLength
)
196 TCHAR szLastFound
[256];
198 HKEY hOtherKey
, hSubKey
;
201 memset(pszSuggestions
, 0, iSuggestionsLength
* sizeof(*pszSuggestions
));
202 iSuggestionsLength
--;
204 /* Are we a root key in HKEY_CLASSES_ROOT? */
205 if ((hRootKey
== HKEY_CLASSES_ROOT
) && pszKeyPath
[0] && !_tcschr(pszKeyPath
, TEXT('\\')))
211 /* Check default key */
212 if (RegQueryStringValue(hRootKey
, pszKeyPath
, NULL
,
213 szBuffer
, sizeof(szBuffer
) / sizeof(szBuffer
[0])) == ERROR_SUCCESS
)
215 /* Sanity check this key; it cannot be empty, nor can it be a
217 if ((szBuffer
[0] != '\0') && _tcsicmp(szBuffer
, pszKeyPath
))
219 if (RegOpenKey(hRootKey
, szBuffer
, &hOtherKey
) == ERROR_SUCCESS
)
221 lstrcpyn(pszSuggestions
, TEXT("HKCR\\"), (int) iSuggestionsLength
);
222 i
= _tcslen(pszSuggestions
);
224 iSuggestionsLength
-= i
;
226 lstrcpyn(pszSuggestions
, szBuffer
, (int) iSuggestionsLength
);
227 i
= MIN(_tcslen(pszSuggestions
) + 1, iSuggestionsLength
);
229 iSuggestionsLength
-= i
;
230 RegCloseKey(hOtherKey
);
233 _tcscpy(szLastFound
, szBuffer
);
234 pszKeyPath
= szLastFound
;
239 while(bFound
&& (iSuggestionsLength
> 0));
241 /* Check CLSID key */
242 if (RegOpenKey(hRootKey
, pszKeyPath
, &hSubKey
) == ERROR_SUCCESS
)
244 if (RegQueryStringValue(hSubKey
, TEXT("CLSID"), NULL
,
245 szBuffer
, sizeof(szBuffer
) / sizeof(szBuffer
[0])) == ERROR_SUCCESS
)
247 lstrcpyn(pszSuggestions
, TEXT("HKCR\\CLSID\\"), (int) iSuggestionsLength
);
248 i
= _tcslen(pszSuggestions
);
250 iSuggestionsLength
-= i
;
252 lstrcpyn(pszSuggestions
, szBuffer
, (int) iSuggestionsLength
);
253 i
= MIN(_tcslen(pszSuggestions
) + 1, iSuggestionsLength
);
255 iSuggestionsLength
-= i
;
257 RegCloseKey(hSubKey
);
263 LRESULT CALLBACK
AddressBarProc(HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
266 static TCHAR s_szNode
[256];
267 oldwndproc
= (WNDPROC
)(LONG_PTR
)GetWindowLongPtr(hwnd
, GWL_USERDATA
);
272 if (wParam
== VK_RETURN
)
274 GetWindowText(hwnd
, s_szNode
, sizeof(s_szNode
) / sizeof(s_szNode
[0]));
275 SelectNode(g_pChildWnd
->hTreeWnd
, s_szNode
);
281 return CallWindowProc(oldwndproc
, hwnd
, uMsg
, wParam
, lParam
);
284 /* fix coords to top-left when SHIFT-F10 is pressed */
285 void FixPointIfContext(POINTS
*pt
, HWND hWnd
)
287 if (pt
->x
== -1 && pt
->y
== -1) {
289 ClientToScreen(hWnd
, &p
);
295 /*******************************************************************************
297 * FUNCTION: ChildWndProc(HWND, unsigned, WORD, LONG)
299 * PURPOSE: Processes messages for the child windows.
301 * WM_COMMAND - process the application menu
302 * WM_PAINT - Paint the main window
303 * WM_DESTROY - post a quit message and return
306 LRESULT CALLBACK
ChildWndProc(HWND hWnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
308 static int last_split
;
310 ChildWnd
* pChildWnd
= g_pChildWnd
;
317 TCHAR buffer
[MAX_PATH
];
318 /* load "My Computer" string */
319 LoadString(hInst
, IDS_MY_COMPUTER
, buffer
, sizeof(buffer
)/sizeof(TCHAR
));
321 g_pChildWnd
= pChildWnd
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(ChildWnd
));
323 if (!pChildWnd
) return 0;
324 _tcsncpy(pChildWnd
->szPath
, buffer
, MAX_PATH
);
325 pChildWnd
->nSplitPos
= 250;
326 pChildWnd
->hWnd
= hWnd
;
327 pChildWnd
->hAddressBarWnd
= CreateWindowEx(WS_EX_CLIENTEDGE
, _T("Edit"), NULL
, WS_CHILD
| WS_VISIBLE
| WS_CHILDWINDOW
| WS_TABSTOP
,
328 CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
,
329 hWnd
, (HMENU
)0, hInst
, 0);
330 pChildWnd
->hTreeWnd
= CreateTreeView(hWnd
, pChildWnd
->szPath
, (HMENU
) TREE_WINDOW
);
331 pChildWnd
->hListWnd
= CreateListView(hWnd
, (HMENU
) LIST_WINDOW
/*, pChildWnd->szPath*/);
332 SetFocus(pChildWnd
->hTreeWnd
);
334 /* set the address bar font */
335 if (pChildWnd
->hAddressBarWnd
)
337 hFont
= (HFONT
)GetStockObject(DEFAULT_GUI_FONT
);
338 SendMessage(pChildWnd
->hAddressBarWnd
,
344 /* Subclass the AddressBar */
345 oldproc
= (WNDPROC
)(LONG_PTR
)GetWindowLongPtr(pChildWnd
->hAddressBarWnd
, GWL_WNDPROC
);
346 SetWindowLongPtr(pChildWnd
->hAddressBarWnd
, GWL_USERDATA
, (DWORD_PTR
)oldproc
);
347 SetWindowLongPtr(pChildWnd
->hAddressBarWnd
, GWL_WNDPROC
, (DWORD_PTR
)AddressBarProc
);
351 if (!_CmdWndProc(hWnd
, message
, wParam
, lParam
)) {
359 if (LOWORD(lParam
) == HTCLIENT
) {
362 ScreenToClient(hWnd
, &pt
);
363 if (pt
.x
>=pChildWnd
->nSplitPos
-SPLIT_WIDTH
/2 && pt
.x
<pChildWnd
->nSplitPos
+SPLIT_WIDTH
/2+1) {
364 SetCursor(LoadCursor(0, IDC_SIZEWE
));
371 DestroyListView(pChildWnd
->hListWnd
);
373 HeapFree(GetProcessHeap(), 0, pChildWnd
);
377 case WM_LBUTTONDOWN
: {
380 pt
= MAKEPOINTS(lParam
);
381 GetClientRect(hWnd
, &rt
);
382 if (pt
.x
>=pChildWnd
->nSplitPos
-SPLIT_WIDTH
/2 && pt
.x
<pChildWnd
->nSplitPos
+SPLIT_WIDTH
/2+1) {
383 last_split
= pChildWnd
->nSplitPos
;
384 draw_splitbar(hWnd
, last_split
);
391 if (GetCapture() == hWnd
) {
394 pt
= MAKEPOINTS(lParam
);
395 GetClientRect(hWnd
, &rt
);
396 pt
.x
= (SHORT
) min(max(pt
.x
, SPLIT_MIN
), rt
.right
- SPLIT_MIN
);
397 draw_splitbar(hWnd
, last_split
);
399 pChildWnd
->nSplitPos
= pt
.x
;
400 ResizeWnd(pChildWnd
, rt
.right
, rt
.bottom
);
405 case WM_CAPTURECHANGED
:
406 if (GetCapture()==hWnd
&& last_split
>=0)
407 draw_splitbar(hWnd
, last_split
);
411 if (wParam
== VK_ESCAPE
)
412 if (GetCapture() == hWnd
) {
414 draw_splitbar(hWnd
, last_split
);
415 GetClientRect(hWnd
, &rt
);
416 ResizeWnd(pChildWnd
, rt
.right
, rt
.bottom
);
419 SetCursor(LoadCursor(0, IDC_ARROW
));
424 if (GetCapture() == hWnd
) {
431 const DWORD Pattern
[4] = {0x5555AAAA, 0x5555AAAA, 0x5555AAAA, 0x5555AAAA};
432 SizingPattern
= CreateBitmap(8, 8, 1, 1, Pattern
);
436 SizingBrush
= CreatePatternBrush(SizingPattern
);
439 pt
= MAKEPOINTS(lParam
);
440 GetClientRect(hWnd
, &rt
);
441 pt
.x
= (SHORT
) min(max(pt
.x
, SPLIT_MIN
), rt
.right
- SPLIT_MIN
);
442 if(last_split
!= pt
.x
)
444 rt
.left
= last_split
-SPLIT_WIDTH
/2;
445 rt
.right
= last_split
+SPLIT_WIDTH
/2+1;
447 OldObj
= SelectObject(hdc
, SizingBrush
);
448 PatBlt(hdc
, rt
.left
, rt
.top
, rt
.right
- rt
.left
, rt
.bottom
- rt
.top
, PATINVERT
);
450 rt
.left
= pt
.x
-SPLIT_WIDTH
/2;
451 rt
.right
= pt
.x
+SPLIT_WIDTH
/2+1;
452 PatBlt(hdc
, rt
.left
, rt
.top
, rt
.right
- rt
.left
, rt
.bottom
- rt
.top
, PATINVERT
);
453 SelectObject(hdc
, OldObj
);
454 ReleaseDC(hWnd
, hdc
);
460 if (pChildWnd
!= NULL
) {
461 SetFocus(pChildWnd
->nFocusPanel
? pChildWnd
->hListWnd
: pChildWnd
->hTreeWnd
);
469 if ((int)wParam
== TREE_WINDOW
) {
470 switch (((LPNMHDR
)lParam
)->code
) {
471 case TVN_ITEMEXPANDING
:
472 return !OnTreeExpanding(pChildWnd
->hTreeWnd
, (NMTREEVIEW
*)lParam
);
473 case TVN_SELCHANGED
: {
474 LPCTSTR keyPath
, rootName
;
478 keyPath
= GetItemPath(pChildWnd
->hTreeWnd
, ((NMTREEVIEW
*)lParam
)->itemNew
.hItem
, &hRootKey
);
480 RefreshListView(pChildWnd
->hListWnd
, hRootKey
, keyPath
);
481 rootName
= get_root_key_name(hRootKey
);
482 fullPath
= HeapAlloc(GetProcessHeap(), 0, (_tcslen(rootName
) + 1 + _tcslen(keyPath
) + 1) * sizeof(TCHAR
));
484 _stprintf(fullPath
, _T("%s\\%s"), rootName
, keyPath
);
485 SendMessage(hStatusBar
, SB_SETTEXT
, 0, (LPARAM
)fullPath
);
486 SendMessage(pChildWnd
->hAddressBarWnd
, WM_SETTEXT
, 0, (LPARAM
)fullPath
);
487 HeapFree(GetProcessHeap(), 0, fullPath
);
491 TCHAR szBuffer
[MAX_PATH
];
492 _sntprintf(szBuffer
, sizeof(szBuffer
) / sizeof(szBuffer
[0]), _T("My Computer\\%s\\%s"), rootName
, keyPath
);
494 if (RegCreateKey(HKEY_CURRENT_USER
,
496 &hKey
) == ERROR_SUCCESS
)
498 RegSetValueEx(hKey
, _T("LastKey"), 0, REG_SZ
, (LPBYTE
) szBuffer
, (DWORD
) _tcslen(szBuffer
) * sizeof(szBuffer
[0]));
507 pChildWnd
->nFocusPanel
= 0;
509 case TVN_BEGINLABELEDIT
:
511 LPNMTVDISPINFO ptvdi
;
512 /* cancel label edit for rootkeys */
513 ptvdi
= (LPNMTVDISPINFO
) lParam
;
514 if (!TreeView_GetParent(pChildWnd
->hTreeWnd
, ptvdi
->item
.hItem
) ||
515 !TreeView_GetParent(pChildWnd
->hTreeWnd
, TreeView_GetParent(pChildWnd
->hTreeWnd
, ptvdi
->item
.hItem
)))
519 case TVN_ENDLABELEDIT
:
524 LPNMTVDISPINFO ptvdi
;
525 LONG lResult
= ERROR_SUCCESS
;
526 TCHAR szBuffer
[MAX_PATH
];
528 ptvdi
= (LPNMTVDISPINFO
) lParam
;
529 if (ptvdi
->item
.pszText
)
531 keyPath
= GetItemPath(pChildWnd
->hTreeWnd
, TreeView_GetParent(pChildWnd
->hTreeWnd
, ptvdi
->item
.hItem
), &hRootKey
);
532 _sntprintf(szBuffer
, sizeof(szBuffer
) / sizeof(szBuffer
[0]), _T("%s\\%s"), keyPath
, ptvdi
->item
.pszText
);
533 keyPath
= GetItemPath(pChildWnd
->hTreeWnd
, ptvdi
->item
.hItem
, &hRootKey
);
534 if (RegOpenKeyEx(hRootKey
, szBuffer
, 0, KEY_READ
, &hKey
) == ERROR_SUCCESS
)
536 lResult
= REG_OPENED_EXISTING_KEY
;
538 (void)TreeView_EditLabel(pChildWnd
->hTreeWnd
, ptvdi
->item
.hItem
);
542 lResult
= RegRenameKey(hRootKey
, keyPath
, ptvdi
->item
.pszText
);
552 if ((int)wParam
== LIST_WINDOW
)
554 switch (((LPNMHDR
)lParam
)->code
) {
556 pChildWnd
->nFocusPanel
= 1;
559 if(!ListWndNotifyProc(pChildWnd
->hListWnd
, wParam
, lParam
, &Result
))
573 if((HWND
)wParam
== pChildWnd
->hListWnd
)
577 pt
= MAKEPOINTS(lParam
);
578 cnt
= ListView_GetSelectedCount(pChildWnd
->hListWnd
);
579 i
= ListView_GetNextItem(pChildWnd
->hListWnd
, -1, LVNI_FOCUSED
| LVNI_SELECTED
);
580 FixPointIfContext(&pt
, pChildWnd
->hListWnd
);
583 TrackPopupMenu(GetSubMenu(hPopupMenus
, PM_NEW
), TPM_RIGHTBUTTON
, pt
.x
, pt
.y
, 0, hFrameWnd
, NULL
);
587 HMENU mnu
= GetSubMenu(hPopupMenus
, PM_MODIFYVALUE
);
588 SetMenuDefaultItem(mnu
, ID_EDIT_MODIFY
, MF_BYCOMMAND
);
589 IsDefault
= IsDefaultValue(pChildWnd
->hListWnd
, i
);
591 EnableMenuItem(mnu
, ID_EDIT_RENAME
, MF_BYCOMMAND
| (IsDefault
? MF_DISABLED
| MF_GRAYED
: MF_ENABLED
));
593 EnableMenuItem(mnu
, ID_EDIT_RENAME
, MF_BYCOMMAND
| MF_DISABLED
| MF_GRAYED
);
594 EnableMenuItem(mnu
, ID_EDIT_MODIFY
, MF_BYCOMMAND
| (cnt
== 1 ? MF_ENABLED
: MF_DISABLED
| MF_GRAYED
));
595 EnableMenuItem(mnu
, ID_EDIT_MODIFY_BIN
, MF_BYCOMMAND
| (cnt
== 1 ? MF_ENABLED
: MF_DISABLED
| MF_GRAYED
));
597 TrackPopupMenu(mnu
, TPM_RIGHTBUTTON
, pt
.x
, pt
.y
, 0, hFrameWnd
, NULL
);
600 else if ((HWND
)wParam
== pChildWnd
->hTreeWnd
)
614 pt
= MAKEPOINTS(lParam
);
617 ScreenToClient(pChildWnd
->hTreeWnd
, &hti
.pt
);
618 (void)TreeView_HitTest(pChildWnd
->hTreeWnd
, &hti
);
620 if ((hti
.flags
& TVHT_ONITEM
) != 0 || (pt
.x
== -1 && pt
.y
== -1))
622 hContextMenu
= GetSubMenu(hPopupMenus
, PM_TREECONTEXT
);
623 (void)TreeView_SelectItem(pChildWnd
->hTreeWnd
, hti
.hItem
);
625 memset(&item
, 0, sizeof(item
));
626 item
.mask
= TVIF_STATE
| TVIF_CHILDREN
;
627 item
.hItem
= hti
.hItem
;
628 (void)TreeView_GetItem(pChildWnd
->hTreeWnd
, &item
);
630 /* Set the Expand/Collapse menu item appropriately */
631 LoadString(hInst
, (item
.state
& TVIS_EXPANDED
) ? IDS_COLLAPSE
: IDS_EXPAND
, buffer
, sizeof(buffer
) / sizeof(buffer
[0]));
632 memset(&mii
, 0, sizeof(mii
));
633 mii
.cbSize
= sizeof(mii
);
634 mii
.fMask
= MIIM_STRING
| MIIM_STATE
| MIIM_ID
;
635 mii
.fState
= (item
.cChildren
> 0) ? MFS_DEFAULT
: MFS_GRAYED
;
636 mii
.wID
= (item
.state
& TVIS_EXPANDED
) ? ID_TREE_COLLAPSEBRANCH
: ID_TREE_EXPANDBRANCH
;
637 mii
.dwTypeData
= (LPTSTR
) buffer
;
638 SetMenuItemInfo(hContextMenu
, 0, TRUE
, &mii
);
640 /* Remove any existing suggestions */
641 memset(&mii
, 0, sizeof(mii
));
642 mii
.cbSize
= sizeof(mii
);
644 GetMenuItemInfo(hContextMenu
, GetMenuItemCount(hContextMenu
) - 1, TRUE
, &mii
);
645 if ((mii
.wID
>= ID_TREE_SUGGESTION_MIN
) && (mii
.wID
<= ID_TREE_SUGGESTION_MAX
))
649 iLastPos
= GetMenuItemCount(hContextMenu
) - 1;
650 GetMenuItemInfo(hContextMenu
, iLastPos
, TRUE
, &mii
);
651 RemoveMenu(hContextMenu
, iLastPos
, MF_BYPOSITION
);
653 while((mii
.wID
>= ID_TREE_SUGGESTION_MIN
) && (mii
.wID
<= ID_TREE_SUGGESTION_MAX
));
656 /* Come up with suggestions */
657 keyPath
= GetItemPath(pChildWnd
->hTreeWnd
, NULL
, &hRootKey
);
658 SuggestKeys(hRootKey
, keyPath
, Suggestions
, sizeof(Suggestions
) / sizeof(Suggestions
[0]));
661 AppendMenu(hContextMenu
, MF_SEPARATOR
, 0, NULL
);
663 LoadString(hInst
, IDS_GOTO_SUGGESTED_KEY
, resource
, sizeof(resource
) / sizeof(resource
[0]));
666 wID
= ID_TREE_SUGGESTION_MIN
;
667 while(*s
&& (wID
<= ID_TREE_SUGGESTION_MAX
))
669 _sntprintf(buffer
, sizeof(buffer
) / sizeof(buffer
[0]), resource
, s
);
671 memset(&mii
, 0, sizeof(mii
));
672 mii
.cbSize
= sizeof(mii
);
673 mii
.fMask
= MIIM_STRING
| MIIM_ID
;
675 mii
.dwTypeData
= buffer
;
676 InsertMenuItem(hContextMenu
, GetMenuItemCount(hContextMenu
), TRUE
, &mii
);
681 FixPointIfContext(&pt
, pChildWnd
->hTreeWnd
);
682 TrackPopupMenu(hContextMenu
, TPM_RIGHTBUTTON
, pt
.x
, pt
.y
, 0, pChildWnd
->hWnd
, NULL
);
689 if (wParam
!= SIZE_MINIMIZED
&& pChildWnd
!= NULL
) {
690 ResizeWnd(pChildWnd
, LOWORD(lParam
), HIWORD(lParam
));
694 return DefWindowProc(hWnd
, message
, wParam
, lParam
);