1 ///////////////////////////////////////////////////////////////////////////////
3 // Purpose: wxRegKey class demo
4 // Author: Vadim Zeitlin
8 // Copyright: (c) 1998 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
9 // Licence: wxWindows license
10 ///////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
14 // ============================================================================
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
19 #include "wx/wxprec.h"
30 #include "wx/treectrl.h"
31 #include "wx/msw/registry.h"
32 #include "wx/msw/imaglist.h"
34 #include "wx/tokenzr.h"
36 // ----------------------------------------------------------------------------
38 // ----------------------------------------------------------------------------
39 class RegApp
: public wxApp
45 // ----------------------------------------------------------------------------
46 // image list with registry icons
47 // ----------------------------------------------------------------------------
48 class RegImageList
: public wxImageList
63 // ----------------------------------------------------------------------------
65 // ----------------------------------------------------------------------------
66 class RegTreeCtrl
: public wxTreeCtrl
70 RegTreeCtrl(wxWindow
*parent
, wxWindowID id
);
71 virtual ~RegTreeCtrl();
74 void OnDeleteItem (wxTreeEvent
& event
);
75 void OnItemExpanding(wxTreeEvent
& event
);
76 void OnSelChanged (wxTreeEvent
& event
);
78 void OnBeginEdit (wxTreeEvent
& event
);
79 void OnEndEdit (wxTreeEvent
& event
);
81 void OnBeginDrag (wxTreeEvent
& event
);
82 void OnEndDrag (wxTreeEvent
& event
);
84 void OnRightClick (wxMouseEvent
& event
);
85 void OnChar (wxKeyEvent
& event
);
86 void OnIdle (wxIdleEvent
& event
);
88 // forwarded notifications (by the frame)
92 void GoTo(const wxString
& location
);
94 void DeleteSelected();
95 void ShowProperties();
96 void CreateNewKey(const wxString
& strName
);
97 void CreateNewTextValue(const wxString
& strName
);
98 void CreateNewBinaryValue(const wxString
& strName
);
101 bool IsKeySelected() const;
104 // structure describing a registry key/value
105 class TreeNode
: public wxTreeItemData
107 WX_DEFINE_ARRAY(TreeNode
*, TreeChildren
);
109 RegTreeCtrl
*m_pTree
; // must be !NULL
110 TreeNode
*m_pParent
; // NULL only for the root node
111 long m_id
; // the id of the tree control item
112 wxString m_strName
; // name of the key/value
113 TreeChildren m_aChildren
; // array of subkeys/values
114 bool m_bKey
; // key or value?
115 wxRegKey
*m_pKey
; // only may be !NULL if m_bKey == true
118 long Id() const { return m_id
; }
119 bool IsRoot() const { return m_pParent
== NULL
; }
120 bool IsKey() const { return m_bKey
; }
121 TreeNode
*Parent() const { return m_pParent
; }
129 bool DeleteChild(TreeNode
*child
);
130 void DestroyChildren();
131 const wxChar
*FullName() const;
133 // get the associated key: make sure the pointer is !NULL
134 wxRegKey
& Key() { if ( !m_pKey
) OnExpand(); return *m_pKey
; }
136 // dtor deletes all children
140 wxImageList
*m_imageList
;
141 wxMenu
*m_pMenuPopup
;
145 TreeNode
*m_draggedItem
; // the item being dragged
146 bool m_copyOnDrop
; // if FALSE, then move
148 bool m_restoreStatus
; // after OnItemExpanding()
150 wxString m_nameOld
; // the initial value of item being renamed
152 TreeNode
*GetNode(const wxTreeEvent
& event
)
153 { return (TreeNode
*)GetItemData((WXHTREEITEM
)event
.GetItem()); }
156 // create a new node and insert it to the tree
157 TreeNode
*InsertNewTreeNode(TreeNode
*pParent
,
158 const wxString
& strName
,
159 int idImage
= RegImageList::ClosedKey
,
160 const wxString
*pstrValue
= NULL
);
161 // add standard registry keys
165 DECLARE_EVENT_TABLE()
168 // ----------------------------------------------------------------------------
169 // the main window of our application
170 // ----------------------------------------------------------------------------
171 class RegFrame
: public wxFrame
175 RegFrame(wxFrame
*parent
, char *title
, int x
, int y
, int w
, int h
);
179 void OnQuit (wxCommandEvent
& event
);
180 void OnAbout(wxCommandEvent
& event
);
181 void OnTest (wxCommandEvent
& event
);
183 void OnGoTo (wxCommandEvent
& event
);
185 void OnExpand (wxCommandEvent
& event
);
186 void OnCollapse(wxCommandEvent
& event
);
187 void OnToggle (wxCommandEvent
& event
);
188 void OnRefresh (wxCommandEvent
& event
);
190 void OnDelete (wxCommandEvent
& event
);
191 void OnNewKey (wxCommandEvent
& event
);
192 void OnNewText (wxCommandEvent
& event
);
193 void OnNewBinary(wxCommandEvent
& event
);
195 void OnInfo (wxCommandEvent
& event
);
197 DECLARE_EVENT_TABLE()
200 RegTreeCtrl
*m_treeCtrl
;
203 // ----------------------------------------------------------------------------
205 // ----------------------------------------------------------------------------
227 // ----------------------------------------------------------------------------
229 // ----------------------------------------------------------------------------
231 BEGIN_EVENT_TABLE(RegFrame
, wxFrame
)
232 EVT_MENU(Menu_Test
, RegFrame::OnTest
)
233 EVT_MENU(Menu_About
, RegFrame::OnAbout
)
234 EVT_MENU(Menu_Quit
, RegFrame::OnQuit
)
235 EVT_MENU(Menu_GoTo
, RegFrame::OnGoTo
)
236 EVT_MENU(Menu_Expand
, RegFrame::OnExpand
)
237 EVT_MENU(Menu_Collapse
, RegFrame::OnCollapse
)
238 EVT_MENU(Menu_Toggle
, RegFrame::OnToggle
)
239 EVT_MENU(Menu_Refresh
, RegFrame::OnRefresh
)
240 EVT_MENU(Menu_Delete
, RegFrame::OnDelete
)
241 EVT_MENU(Menu_NewKey
, RegFrame::OnNewKey
)
242 EVT_MENU(Menu_NewText
, RegFrame::OnNewText
)
243 EVT_MENU(Menu_NewBinary
,RegFrame::OnNewBinary
)
244 EVT_MENU(Menu_Info
, RegFrame::OnInfo
)
247 BEGIN_EVENT_TABLE(RegTreeCtrl
, wxTreeCtrl
)
248 EVT_TREE_DELETE_ITEM (Ctrl_RegTree
, RegTreeCtrl::OnDeleteItem
)
249 EVT_TREE_ITEM_EXPANDING(Ctrl_RegTree
, RegTreeCtrl::OnItemExpanding
)
250 EVT_TREE_SEL_CHANGED (Ctrl_RegTree
, RegTreeCtrl::OnSelChanged
)
252 EVT_TREE_BEGIN_LABEL_EDIT(Ctrl_RegTree
, RegTreeCtrl::OnBeginEdit
)
253 EVT_TREE_END_LABEL_EDIT (Ctrl_RegTree
, RegTreeCtrl::OnEndEdit
)
255 EVT_TREE_BEGIN_DRAG (Ctrl_RegTree
, RegTreeCtrl::OnBeginDrag
)
256 EVT_TREE_BEGIN_RDRAG (Ctrl_RegTree
, RegTreeCtrl::OnBeginDrag
)
257 EVT_TREE_END_DRAG (Ctrl_RegTree
, RegTreeCtrl::OnEndDrag
)
259 EVT_CHAR (RegTreeCtrl::OnChar
)
260 EVT_RIGHT_DOWN(RegTreeCtrl::OnRightClick
)
261 EVT_IDLE (RegTreeCtrl::OnIdle
)
264 // ============================================================================
266 // ============================================================================
268 // ----------------------------------------------------------------------------
270 // ----------------------------------------------------------------------------
272 // create the "registry operations" menu
273 wxMenu
*CreateRegistryMenu()
275 wxMenu
*pMenuNew
= new wxMenu
;
276 pMenuNew
->Append(Menu_NewKey
, "&Key", "Create a new key");
277 pMenuNew
->AppendSeparator();
278 pMenuNew
->Append(Menu_NewText
, "&Text value", "Create a new text value");
279 pMenuNew
->Append(Menu_NewBinary
, "&Binary value", "Create a new binary value");
281 wxMenu
*pMenuReg
= new wxMenu
;
282 pMenuReg
->Append(Menu_New
, "&New", pMenuNew
);
283 pMenuReg
->Append(Menu_Delete
, "&Delete...", "Delete selected key/value");
284 pMenuReg
->AppendSeparator();
285 pMenuReg
->Append(Menu_GoTo
, "&Go to...\tCtrl-G", "Go to registry key");
286 pMenuReg
->Append(Menu_Expand
, "&Expand", "Expand current key");
287 pMenuReg
->Append(Menu_Collapse
, "&Collapse", "Collapse current key");
288 pMenuReg
->Append(Menu_Toggle
, "&Toggle", "Toggle current key");
289 pMenuReg
->AppendSeparator();
290 pMenuReg
->Append(Menu_Refresh
, "&Refresh", "Refresh the subtree");
291 pMenuReg
->AppendSeparator();
292 pMenuReg
->Append(Menu_Info
, "&Properties","Information about current selection");
297 // ----------------------------------------------------------------------------
299 // ----------------------------------------------------------------------------
300 IMPLEMENT_APP(RegApp
)
302 // `Main program' equivalent, creating windows and returning main app frame
303 bool RegApp::OnInit()
305 // create the main frame window and show it
306 RegFrame
*frame
= new RegFrame(NULL
, "wxRegTest", 50, 50, 600, 350);
314 // ----------------------------------------------------------------------------
316 // ----------------------------------------------------------------------------
318 RegFrame::RegFrame(wxFrame
*parent
, char *title
, int x
, int y
, int w
, int h
)
319 : wxFrame(parent
, -1, title
, wxPoint(x
, y
), wxSize(w
, h
))
321 // this reduces flicker effects
322 SetBackgroundColour(wxColour(255, 255, 255));
326 SetIcon(wxIcon("app_icon"));
330 wxMenu
*pMenuFile
= new wxMenu
;
331 pMenuFile
->Append(Menu_Test
, "Te&st", "Test key creation");
332 pMenuFile
->AppendSeparator();
333 pMenuFile
->Append(Menu_About
, "&About...", "Show an extraordinarly beautiful dialog");
334 pMenuFile
->AppendSeparator();
335 pMenuFile
->Append(Menu_Quit
, "E&xit", "Quit this program");
337 wxMenuBar
*pMenu
= new wxMenuBar
;
338 pMenu
->Append(pMenuFile
, "&File");
339 pMenu
->Append(CreateRegistryMenu(), "&Registry");
342 // create child controls
343 // ---------------------
344 m_treeCtrl
= new RegTreeCtrl(this, Ctrl_RegTree
);
346 // create the status line
347 // ----------------------
351 RegFrame::~RegFrame()
353 // this makes deletion of it *much* quicker
357 void RegFrame::OnQuit(wxCommandEvent
& event
)
362 void RegFrame::OnAbout(wxCommandEvent
& event
)
364 wxMessageDialog
dialog(this,
365 "wxRegistry sample\n"
366 "© 1998, 2000 Vadim Zeitlin",
367 "About wxRegTest", wxOK
);
372 void RegFrame::OnTest(wxCommandEvent
& WXUNUSED(event
))
374 m_treeCtrl
->OnMenuTest();
377 void RegFrame::OnGoTo(wxCommandEvent
& WXUNUSED(event
))
379 static wxString s_location
= _T("HKEY_CURRENT_USER\\Software\\wxWindows");
381 wxString location
= wxGetTextFromUser
383 _T("Enter the location to go to:"),
384 _T("wxRegTest question"),
391 s_location
= location
;
392 m_treeCtrl
->GoTo(location
);
395 void RegFrame::OnExpand(wxCommandEvent
& WXUNUSED(event
))
397 m_treeCtrl
->ExpandItem(m_treeCtrl
->GetSelection(), wxTREE_EXPAND_EXPAND
);
400 void RegFrame::OnCollapse(wxCommandEvent
& WXUNUSED(event
))
402 m_treeCtrl
->ExpandItem(m_treeCtrl
->GetSelection(), wxTREE_EXPAND_COLLAPSE
);
405 void RegFrame::OnToggle(wxCommandEvent
& WXUNUSED(event
))
407 m_treeCtrl
->ExpandItem(m_treeCtrl
->GetSelection(), wxTREE_EXPAND_TOGGLE
);
410 void RegFrame::OnRefresh(wxCommandEvent
& WXUNUSED(event
))
412 m_treeCtrl
->Refresh();
415 void RegFrame::OnDelete(wxCommandEvent
& WXUNUSED(event
))
417 m_treeCtrl
->DeleteSelected();
420 void RegFrame::OnNewKey(wxCommandEvent
& WXUNUSED(event
))
422 if ( m_treeCtrl
->IsKeySelected() ) {
423 m_treeCtrl
->CreateNewKey(
424 wxGetTextFromUser("Enter the name of the new key"));
428 void RegFrame::OnNewText(wxCommandEvent
& WXUNUSED(event
))
430 if ( m_treeCtrl
->IsKeySelected() ) {
431 m_treeCtrl
->CreateNewTextValue(
432 wxGetTextFromUser("Enter the name for the new text value"));
436 void RegFrame::OnNewBinary(wxCommandEvent
& WXUNUSED(event
))
438 if ( m_treeCtrl
->IsKeySelected() ) {
439 m_treeCtrl
->CreateNewBinaryValue(
440 wxGetTextFromUser("Enter the name for the new binary value"));
444 void RegFrame::OnInfo(wxCommandEvent
& WXUNUSED(event
))
446 m_treeCtrl
->ShowProperties();
449 // ----------------------------------------------------------------------------
451 // ----------------------------------------------------------------------------
452 RegImageList::RegImageList() : wxImageList(16, 16, TRUE
)
454 // should be in sync with enum RegImageList::RegIcon
455 static const char *aszIcons
[] = { "key1","key2","key3","value1","value2" };
456 wxString str
= "icon_";
457 for ( unsigned int n
= 0; n
< WXSIZEOF(aszIcons
); n
++ ) {
458 Add(wxIcon(str
+ aszIcons
[n
], wxBITMAP_TYPE_ICO_RESOURCE
));
462 // ----------------------------------------------------------------------------
464 // ----------------------------------------------------------------------------
466 // create a new tree item and insert it into the tree
467 RegTreeCtrl::TreeNode
*RegTreeCtrl::InsertNewTreeNode(TreeNode
*pParent
,
468 const wxString
& strName
,
470 const wxString
*pstrValue
)
472 // create new item & insert it
473 TreeNode
*pNewNode
= new TreeNode
;
474 pNewNode
->m_pTree
= this;
475 pNewNode
->m_pParent
= pParent
;
476 pNewNode
->m_strName
= strName
;
477 pNewNode
->m_bKey
= pstrValue
== NULL
;
478 pNewNode
->m_pKey
= NULL
;
479 pNewNode
->m_id
= InsertItem(pParent
? pParent
->Id() : 0,
480 pNewNode
->IsKey() ? strName
: *pstrValue
,
483 wxASSERT_MSG( pNewNode
->m_id
, wxT("can't create tree control item!"));
485 // save the pointer in the item
486 SetItemData(pNewNode
->m_id
, pNewNode
);
488 // add it to the list of parent's children
489 if ( pParent
!= NULL
) {
490 pParent
->m_aChildren
.Add(pNewNode
);
493 if ( pNewNode
->IsKey() ) {
494 SetItemHasChildren(pNewNode
->Id());
496 if ( !pNewNode
->IsRoot() ) {
497 // set the expanded icon as well
498 SetItemImage(pNewNode
->Id(),
499 RegImageList::OpenedKey
,
500 wxTreeItemIcon_Expanded
);
507 RegTreeCtrl::RegTreeCtrl(wxWindow
*parent
, wxWindowID id
)
508 : wxTreeCtrl(parent
, id
, wxDefaultPosition
, wxDefaultSize
,
509 wxTR_HAS_BUTTONS
| wxTR_EDIT_LABELS
| wxSUNKEN_BORDER
)
512 m_draggedItem
= NULL
;
513 m_restoreStatus
= FALSE
;
515 // create the image list
516 // ---------------------
517 m_imageList
= new RegImageList
;
518 SetImageList(m_imageList
, wxIMAGE_LIST_NORMAL
);
522 m_pRoot
= InsertNewTreeNode(NULL
, "Registry Root", RegImageList::Root
);
526 m_pMenuPopup
= CreateRegistryMenu();
529 RegTreeCtrl::~RegTreeCtrl()
532 // delete m_pRoot; -- this is done by the tree now
536 void RegTreeCtrl::AddStdKeys()
538 for ( unsigned int ui
= 0; ui
< wxRegKey::nStdKeys
; ui
++ ) {
539 InsertNewTreeNode(m_pRoot
, wxRegKey::GetStdKeyName(ui
));
543 // ----------------------------------------------------------------------------
545 // ----------------------------------------------------------------------------
547 void RegTreeCtrl::OnIdle(wxIdleEvent
& WXUNUSED(event
))
549 if ( m_restoreStatus
) {
550 // restore it after OnItemExpanding()
551 wxLogStatus(wxT("Ok"));
552 wxSetCursor(*wxSTANDARD_CURSOR
);
554 m_restoreStatus
= FALSE
;
558 void RegTreeCtrl::OnRightClick(wxMouseEvent
& event
)
561 long lId
= HitTest(wxPoint(event
.GetX(), event
.GetY()), iFlags
);
562 if ( iFlags
& wxTREE_HITTEST_ONITEMLABEL
) {
563 // select the item first
566 //else: take the currently selected item if click not on item
568 PopupMenu(m_pMenuPopup
, event
.GetX(), event
.GetY());
572 void RegTreeCtrl::OnDeleteItem(wxTreeEvent
& event
)
576 // test the key creation functions
577 void RegTreeCtrl::OnMenuTest()
579 long lId
= GetSelection();
580 TreeNode
*pNode
= (TreeNode
*)GetItemData(lId
);
582 wxCHECK_RET( pNode
!= NULL
, wxT("tree item without data?") );
584 if ( pNode
->IsRoot() ) {
585 wxLogError(wxT("Can't create a subkey under the root key."));
588 if ( !pNode
->IsKey() ) {
589 wxLogError(wxT("Can't create a subkey under a value!"));
593 wxRegKey
key1(pNode
->Key(), "key1");
594 if ( key1
.Create() ) {
595 wxRegKey
key2a(key1
, "key2a"), key2b(key1
, "key2b");
596 if ( key2a
.Create() && key2b
.Create() ) {
597 // put some values under the newly created keys
598 key1
.SetValue(wxT("first_term"), "10");
599 key1
.SetValue(wxT("second_term"), "7");
600 key2a
= "this is the unnamed value";
601 key2b
.SetValue(wxT("sum"), 17);
605 wxLogStatus(wxT("Test keys successfully added."));
610 wxLogError(wxT("Creation of test keys failed."));
613 void RegTreeCtrl::OnChar(wxKeyEvent
& event
)
615 switch ( event
.KeyCode() )
622 if ( event
.AltDown() )
633 void RegTreeCtrl::OnSelChanged(wxTreeEvent
& event
)
635 wxFrame
*pFrame
= (wxFrame
*)(wxWindow::GetParent());
636 pFrame
->SetStatusText(GetNode(event
)->FullName(), 1);
639 void RegTreeCtrl::OnItemExpanding(wxTreeEvent
& event
)
641 TreeNode
*pNode
= GetNode(event
);
642 bool bExpanding
= event
.GetCode() == wxTREE_EXPAND_EXPAND
;
644 // expansion might take some time
645 wxSetCursor(*wxHOURGLASS_CURSOR
);
646 wxLogStatus(wxT("Working..."));
647 wxYield(); // to give the status line a chance to refresh itself
648 m_restoreStatus
= TRUE
; // some time later...
650 if ( pNode
->IsKey() ) {
652 // expanding: add subkeys/values
653 if ( !pNode
->OnExpand() )
657 // collapsing: clean up
663 void RegTreeCtrl::OnBeginEdit(wxTreeEvent
& event
)
665 TreeNode
*pNode
= GetNode(event
);
666 if ( pNode
->IsRoot() || pNode
->Parent()->IsRoot() ) {
667 wxLogStatus(_T("This registry key can't be renamed."));
672 m_nameOld
= pNode
->m_strName
;
676 void RegTreeCtrl::OnEndEdit(wxTreeEvent
& event
)
680 wxString name
= event
.GetLabel();
682 TreeNode
*pNode
= GetNode(event
);
683 if ( pNode
->IsKey() )
685 wxRegKey
& key
= pNode
->Key();
686 ok
= key
.Rename(name
);
690 pNode
= pNode
->Parent();
691 wxRegKey
& key
= pNode
->Key();
693 ok
= key
.RenameValue(m_nameOld
, name
);
697 wxLogError(_T("Failed to rename '%s' to '%s'."),
698 m_nameOld
.c_str(), name
.c_str());
700 #if 0 // MSW tree ctrl doesn't like this at all, it hangs
707 void RegTreeCtrl::OnBeginDrag(wxTreeEvent
& event
)
709 m_copyOnDrop
= event
.GetEventType() == wxEVT_COMMAND_TREE_BEGIN_DRAG
;
711 TreeNode
*pNode
= GetNode(event
);
712 if ( pNode
->IsRoot() || pNode
->Parent()->IsRoot() )
714 wxLogStatus(wxT("This registry key can't be %s."),
715 m_copyOnDrop
? wxT("copied") : wxT("moved"));
719 wxLogStatus(wxT("%s item %s..."),
720 m_copyOnDrop
? wxT("Copying") : wxT("Moving"),
723 m_draggedItem
= pNode
;
729 void RegTreeCtrl::OnEndDrag(wxTreeEvent
& event
)
731 wxCHECK_RET( m_draggedItem
, wxT("end drag without begin drag?") );
733 // clear the pointer anyhow
734 TreeNode
*src
= m_draggedItem
;
735 m_draggedItem
= NULL
;
737 // where are we going to drop it?
738 TreeNode
*dst
= GetNode(event
);
739 if ( dst
&& !dst
->IsKey() ) {
740 // we need a parent key
743 if ( !dst
|| dst
->IsRoot() ) {
744 wxLogError(wxT("Can't create a key here."));
749 bool isKey
= src
->IsKey();
750 if ( (isKey
&& (src
== dst
)) ||
751 (!isKey
&& (dst
->Parent() == src
)) ) {
752 wxLogStatus(wxT("Can't copy something on itself"));
757 // remove the "Registry Root\\" from the full name
758 wxString nameSrc
, nameDst
;
759 nameSrc
<< wxString(src
->FullName()).AfterFirst('\\');
760 nameDst
<< wxString(dst
->FullName()).AfterFirst('\\') << '\\'
761 << wxString(src
->FullName()).AfterLast('\\');
763 wxString verb
= m_copyOnDrop
? "copy" : "move";
764 wxString what
= isKey
? "key" : "value";
766 if ( wxMessageBox(wxString::Format
768 wxT("Do you really want to %s the %s %s to %s?"),
775 wxICON_QUESTION
| wxYES_NO
| wxCANCEL
, this) != wxYES
) {
781 wxRegKey
& key
= src
->Key();
782 wxRegKey
keyDst(dst
->Key(), src
->m_strName
);
783 ok
= keyDst
.Create(FALSE
);
785 wxLogError(wxT("Key '%s' already exists"));
788 ok
= key
.Copy(keyDst
);
791 if ( ok
&& !m_copyOnDrop
) {
792 // delete the old key
793 ok
= key
.DeleteSelf();
795 src
->Parent()->Refresh();
800 wxRegKey
& key
= src
->Parent()->Key();
801 ok
= key
.CopyValue(src
->m_strName
, dst
->Key());
802 if ( ok
&& !m_copyOnDrop
) {
803 // we moved it, so delete the old one
804 ok
= key
.DeleteValue(src
->m_strName
);
809 wxLogError(wxT("Failed to %s registry %s."),
810 verb
.c_str(), what
.c_str());
817 // ----------------------------------------------------------------------------
818 // TreeNode implementation
819 // ----------------------------------------------------------------------------
820 bool RegTreeCtrl::TreeNode::OnExpand()
822 // we add children only once
823 if ( !m_aChildren
.IsEmpty() ) {
824 // we've been already expanded
829 // we're the root key
830 m_pTree
->AddStdKeys();
834 if ( Parent()->IsRoot() ) {
835 // we're a standard key
836 m_pKey
= new wxRegKey(m_strName
);
839 // we're a normal key
840 m_pKey
= new wxRegKey(*(Parent()->m_pKey
), m_strName
);
843 if ( !m_pKey
->Open() ) {
844 wxLogError(wxT("The key '%s' can't be opened."), FullName());
848 // if we're empty, we shouldn't be expandable at all
851 // enumeration variables
856 // enumerate all subkeys
857 bCont
= m_pKey
->GetFirstKey(str
, l
);
859 m_pTree
->InsertNewTreeNode(this, str
, RegImageList::ClosedKey
);
860 bCont
= m_pKey
->GetNextKey(str
, l
);
862 // we have at least this key...
866 // enumerate all values
867 bCont
= m_pKey
->GetFirstValue(str
, l
);
871 strItem
= "<default>";
876 // determine the appropriate icon
877 RegImageList::Icon icon
;
878 switch ( m_pKey
->GetValueType(str
) ) {
879 case wxRegKey::Type_String
:
880 case wxRegKey::Type_Expand_String
:
881 case wxRegKey::Type_Multi_String
:
884 icon
= RegImageList::TextValue
;
885 m_pKey
->QueryValue(str
, strValue
);
890 case wxRegKey::Type_None
:
891 // @@ handle the error...
892 icon
= RegImageList::BinaryValue
;
895 case wxRegKey::Type_Dword
:
898 m_pKey
->QueryValue(str
, &l
);
905 icon
= RegImageList::BinaryValue
;
908 m_pTree
->InsertNewTreeNode(this, str
, icon
, &strItem
);
909 bCont
= m_pKey
->GetNextValue(str
, l
);
911 // we have at least this value...
916 // this is for the case when our last child was just deleted
917 wxTreeItemId
theId(Id()); // Temp variable seems necessary for BC++
918 m_pTree
->Collapse(theId
);
920 // we won't be expanded any more
921 m_pTree
->SetItemHasChildren(theId
, FALSE
);
927 void RegTreeCtrl::TreeNode::OnCollapse()
935 void RegTreeCtrl::TreeNode::Refresh()
940 wxTreeItemId
theId(Id()); // Temp variable seems necessary for BC++
941 bool wasExpanded
= m_pTree
->IsExpanded(theId
);
943 m_pTree
->Collapse(theId
);
946 m_pTree
->SetItemHasChildren(theId
);
948 m_pTree
->Expand(theId
);
953 bool RegTreeCtrl::TreeNode::DeleteChild(TreeNode
*child
)
955 int index
= m_aChildren
.Index(child
);
956 wxCHECK_MSG( index
!= wxNOT_FOUND
, FALSE
,
957 wxT("our child in tree should be in m_aChildren") );
959 m_aChildren
.RemoveAt((size_t)index
);
962 if ( child
->IsKey() ) {
963 // must close key before deleting it
966 ok
= Key().DeleteKey(child
->m_strName
);
969 ok
= Key().DeleteValue(child
->m_strName
);
973 wxTreeItemId
theId(child
->Id()); // Temp variable seems necessary for BC++
974 m_pTree
->Delete(theId
);
982 void RegTreeCtrl::TreeNode::DestroyChildren()
984 // destroy all children
985 size_t nCount
= m_aChildren
.GetCount();
986 for ( size_t n
= 0; n
< nCount
; n
++ ) {
987 long lId
= m_aChildren
[n
]->Id();
988 // no, wxTreeCtrl will do it
989 //delete m_aChildren[n];
990 wxTreeItemId
theId(lId
); // Temp variable seems necessary for BC++
991 m_pTree
->Delete(theId
);
997 RegTreeCtrl::TreeNode::~TreeNode()
1002 const wxChar
*RegTreeCtrl::TreeNode::FullName() const
1004 static wxString s_strName
;
1007 return wxT("Registry Root");
1010 // our own registry key might not (yet) exist or we might be a value,
1011 // so just use the parent's and concatenate
1012 s_strName
= Parent()->FullName();
1013 s_strName
<< wxT('\\') << m_strName
;
1019 // ----------------------------------------------------------------------------
1020 // operations on RegTreeCtrl
1021 // ----------------------------------------------------------------------------
1023 void RegTreeCtrl::GoTo(const wxString
& location
)
1025 wxStringTokenizer
tk(location
, _T("\\"));
1027 wxTreeItemId id
= GetRootItem();
1029 while ( tk
.HasMoreTokens() ) {
1030 wxString subkey
= tk
.GetNextToken();
1032 wxTreeItemId idCurrent
= id
;
1033 if ( !IsExpanded(idCurrent
) )
1037 id
= GetFirstChild(idCurrent
, dummy
);
1039 if ( idCurrent
== GetRootItem() ) {
1040 // special case: we understand both HKCU and HKEY_CURRENT_USER here
1041 for ( size_t key
= 0; key
< wxRegKey::nStdKeys
; key
++ ) {
1042 if ( subkey
== wxRegKey::GetStdKeyName(key
) ||
1043 subkey
== wxRegKey::GetStdKeyShortName(key
) ) {
1047 id
= GetNextChild(idCurrent
, dummy
);
1051 // enum all children
1052 while ( id
.IsOk() ) {
1053 if ( subkey
== ((TreeNode
*)GetItemData(id
))->m_strName
)
1056 id
= GetNextChild(idCurrent
, dummy
);
1061 wxLogError(_T("No such key '%s'."), location
.c_str());
1071 void RegTreeCtrl::DeleteSelected()
1073 long lCurrent
= GetSelection(),
1074 lParent
= GetParent(lCurrent
);
1076 if ( lParent
== 0 ) {
1077 wxLogError(wxT("Can't delete root key."));
1081 TreeNode
*pCurrent
= (TreeNode
*)GetItemData(lCurrent
),
1082 *pParent
= (TreeNode
*)GetItemData(lParent
);
1084 wxCHECK_RET(pCurrent
&& pParent
, wxT("either node or parent without data?"));
1086 if ( pParent
->IsRoot() ) {
1087 wxLogError(wxT("Can't delete standard key."));
1091 wxString what
= pCurrent
->IsKey() ? "key" : "value";
1092 if ( wxMessageBox(wxString::Format
1094 wxT("Do you really want to delete this %s?"),
1098 wxICON_QUESTION
| wxYES_NO
| wxCANCEL
, this) != wxYES
) {
1102 pParent
->DeleteChild(pCurrent
);
1105 void RegTreeCtrl::CreateNewKey(const wxString
& strName
)
1107 long lCurrent
= GetSelection();
1108 TreeNode
*pCurrent
= (TreeNode
*)GetItemData(lCurrent
);
1110 wxCHECK_RET( pCurrent
!= NULL
, wxT("node without data?") );
1112 wxASSERT( pCurrent
->IsKey() ); // check must have been done before
1114 if ( pCurrent
->IsRoot() ) {
1115 wxLogError(wxT("Can't create a new key under the root key."));
1119 wxRegKey
key(pCurrent
->Key(), strName
);
1121 pCurrent
->Refresh();
1124 void RegTreeCtrl::CreateNewTextValue(const wxString
& strName
)
1126 long lCurrent
= GetSelection();
1127 TreeNode
*pCurrent
= (TreeNode
*)GetItemData(lCurrent
);
1129 wxCHECK_RET( pCurrent
!= NULL
, wxT("node without data?") );
1131 wxASSERT( pCurrent
->IsKey() ); // check must have been done before
1133 if ( pCurrent
->IsRoot() ) {
1134 wxLogError(wxT("Can't create a new value under the root key."));
1138 if ( pCurrent
->Key().SetValue(strName
, "") )
1139 pCurrent
->Refresh();
1142 void RegTreeCtrl::CreateNewBinaryValue(const wxString
& strName
)
1144 long lCurrent
= GetSelection();
1145 TreeNode
*pCurrent
= (TreeNode
*)GetItemData(lCurrent
);
1147 wxCHECK_RET( pCurrent
!= NULL
, wxT("node without data?") );
1149 wxASSERT( pCurrent
->IsKey() ); // check must have been done before
1151 if ( pCurrent
->IsRoot() ) {
1152 wxLogError(wxT("Can't create a new value under the root key."));
1156 if ( pCurrent
->Key().SetValue(strName
, 0) )
1157 pCurrent
->Refresh();
1160 void RegTreeCtrl::ShowProperties()
1162 long lCurrent
= GetSelection();
1163 TreeNode
*pCurrent
= (TreeNode
*)GetItemData(lCurrent
);
1165 if ( !pCurrent
|| pCurrent
->IsRoot() )
1167 wxLogStatus(wxT("No properties"));
1172 if ( pCurrent
->IsKey() )
1174 const wxRegKey
& key
= pCurrent
->Key();
1175 size_t nSubKeys
, nValues
;
1176 if ( !key
.GetKeyInfo(&nSubKeys
, NULL
, &nValues
, NULL
) )
1178 wxLogError(wxT("Couldn't get key info"));
1182 wxLogMessage(wxT("Key '%s' has %u subkeys and %u values."),
1183 key
.GetName().c_str(), nSubKeys
, nValues
);
1186 else // it's a value
1188 TreeNode
*parent
= pCurrent
->Parent();
1189 wxCHECK_RET( parent
, wxT("reg value without key?") );
1191 const wxRegKey
& key
= parent
->Key();
1192 const wxChar
*value
= pCurrent
->m_strName
.c_str();
1193 wxLogMessage(wxT("Value '%s' under the key '%s' is of type ")
1196 parent
->m_strName
.c_str(),
1197 key
.GetValueType(value
),
1198 key
.IsNumericValue(value
) ? wxT("numeric") : wxT("string"));
1203 bool RegTreeCtrl::IsKeySelected() const
1205 long lCurrent
= GetSelection();
1206 TreeNode
*pCurrent
= (TreeNode
*)GetItemData(lCurrent
);
1208 wxCHECK( pCurrent
!= NULL
, FALSE
);
1210 return pCurrent
->IsKey();
1213 void RegTreeCtrl::Refresh()
1215 long lId
= GetSelection();
1219 TreeNode
*pNode
= (TreeNode
*)GetItemData(lId
);
1221 wxCHECK_RET( pNode
!= NULL
, wxT("tree item without data?") );