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"
33 // ----------------------------------------------------------------------------
35 // ----------------------------------------------------------------------------
36 class RegApp
: public wxApp
42 // ----------------------------------------------------------------------------
43 // image list with registry icons
44 // ----------------------------------------------------------------------------
45 class RegImageList
: public wxImageList
60 // array of children of the node
62 WX_DEFINE_ARRAY(TreeNode
*, TreeChildren
);
64 // ----------------------------------------------------------------------------
66 // ----------------------------------------------------------------------------
67 class RegTreeCtrl
: public wxTreeCtrl
71 RegTreeCtrl(wxWindow
*parent
, wxWindowID id
);
72 virtual ~RegTreeCtrl();
75 void OnDeleteItem (wxTreeEvent
& event
);
76 void OnItemExpanding(wxTreeEvent
& event
);
77 void OnSelChanged (wxTreeEvent
& event
);
79 void OnRightClick (wxMouseEvent
& event
);
80 void OnChar (wxKeyEvent
& event
);
82 // forwarded notifications (by the frame)
86 void DeleteSelected();
87 void CreateNewKey(const wxString
& strName
);
88 void CreateNewTextValue(const wxString
& strName
);
89 void CreateNewBinaryValue(const wxString
& strName
);
92 bool IsKeySelected() const;
94 DECLARE_EVENT_TABLE();
98 // structure describing a registry key/value
101 RegTreeCtrl
*m_pTree
; // must be !NULL
102 TreeNode
*m_pParent
; // NULL only for the root node
103 long m_id
; // the id of the tree control item
104 wxString m_strName
; // name of the key/value
105 TreeChildren m_aChildren
; // array of subkeys/values
106 bool m_bKey
; // key or value?
107 wxRegKey
*m_pKey
; // only may be !NULL if m_bKey == true
108 long m_lDummy
; // dummy subkey (to make expansion possible)
111 TreeNode() { m_lDummy
= 0; }
114 long Id() const { return m_id
; }
115 bool IsRoot() const { return m_pParent
== NULL
; }
116 bool IsKey() const { return m_bKey
; }
117 TreeNode
*Parent() const { return m_pParent
; }
124 void Refresh() { OnCollapse(); OnExpand(); }
126 void DestroyChildren();
127 const char *FullName() const;
129 // get the associated key: make sure the pointer is !NULL
130 wxRegKey
& Key() { if ( !m_pKey
) OnExpand(); return *m_pKey
; }
132 // dtor deletes all children
136 wxMenu
*m_pMenuPopup
;
138 wxImageList
*m_imageList
;
140 TreeNode
*GetNode(const wxTreeEvent
& event
)
141 { return (TreeNode
*)GetItemData(event
.m_item
.m_itemId
); }
144 // create a new node and insert it to the tree
145 TreeNode
*InsertNewTreeNode(TreeNode
*pParent
,
146 const wxString
& strName
,
147 int idImage
= RegImageList::ClosedKey
,
148 const wxString
*pstrValue
= NULL
);
149 // add standard registry keys
153 // ----------------------------------------------------------------------------
154 // the main window of our application
155 // ----------------------------------------------------------------------------
156 class RegFrame
: public wxFrame
160 RegFrame(wxFrame
*parent
, char *title
, int x
, int y
, int w
, int h
);
161 virtual ~RegFrame(void);
164 void OnQuit (wxCommandEvent
& event
);
165 void OnAbout(wxCommandEvent
& event
);
166 void OnTest (wxCommandEvent
& event
);
168 void OnExpand (wxCommandEvent
& event
);
169 void OnCollapse(wxCommandEvent
& event
);
170 void OnToggle (wxCommandEvent
& event
);
172 void OnDelete (wxCommandEvent
& event
);
173 void OnNewKey (wxCommandEvent
& event
);
174 void OnNewText (wxCommandEvent
& event
);
175 void OnNewBinary(wxCommandEvent
& event
);
177 bool OnClose () { return TRUE
; }
179 DECLARE_EVENT_TABLE();
182 RegTreeCtrl
*m_treeCtrl
;
185 // ----------------------------------------------------------------------------
187 // ----------------------------------------------------------------------------
206 // ----------------------------------------------------------------------------
208 // ----------------------------------------------------------------------------
210 BEGIN_EVENT_TABLE(RegFrame
, wxFrame
)
211 EVT_MENU(Menu_Test
, RegFrame::OnTest
)
212 EVT_MENU(Menu_About
, RegFrame::OnAbout
)
213 EVT_MENU(Menu_Quit
, RegFrame::OnQuit
)
214 EVT_MENU(Menu_Expand
, RegFrame::OnExpand
)
215 EVT_MENU(Menu_Collapse
, RegFrame::OnCollapse
)
216 EVT_MENU(Menu_Toggle
, RegFrame::OnToggle
)
217 EVT_MENU(Menu_Delete
, RegFrame::OnDelete
)
218 EVT_MENU(Menu_NewKey
, RegFrame::OnNewKey
)
219 EVT_MENU(Menu_NewText
, RegFrame::OnNewText
)
220 EVT_MENU(Menu_NewBinary
,RegFrame::OnNewBinary
)
223 BEGIN_EVENT_TABLE(RegTreeCtrl
, wxTreeCtrl
)
224 EVT_TREE_DELETE_ITEM (Ctrl_RegTree
, RegTreeCtrl::OnDeleteItem
)
225 EVT_TREE_ITEM_EXPANDING(Ctrl_RegTree
, RegTreeCtrl::OnItemExpanding
)
226 EVT_TREE_SEL_CHANGED (Ctrl_RegTree
, RegTreeCtrl::OnSelChanged
)
228 EVT_CHAR (RegTreeCtrl::OnChar
)
229 EVT_RIGHT_DOWN(RegTreeCtrl::OnRightClick
)
232 // ============================================================================
234 // ============================================================================
236 // ----------------------------------------------------------------------------
238 // ----------------------------------------------------------------------------
240 // create the "registry operations" menu
241 wxMenu
*CreateRegistryMenu()
243 wxMenu
*pMenuNew
= new wxMenu
;
244 pMenuNew
->Append(Menu_NewKey
, "&Key", "Create a new key");
245 pMenuNew
->AppendSeparator();
246 pMenuNew
->Append(Menu_NewText
, "&Text value", "Create a new text value");
247 pMenuNew
->Append(Menu_NewBinary
, "&Binary value", "Create a new binary value");
249 wxMenu
*pMenuReg
= new wxMenu
;
250 pMenuReg
->Append(Menu_New
, "&New", pMenuNew
);
251 pMenuReg
->Append(Menu_Delete
, "&Delete...", "Delete selected key/value");
252 pMenuReg
->AppendSeparator();
253 pMenuReg
->Append(Menu_Expand
, "&Expand", "Expand current key");
254 pMenuReg
->Append(Menu_Collapse
, "&Collapse", "Collapse current key");
255 pMenuReg
->Append(Menu_Toggle
, "&Toggle", "Toggle current key");
260 // ----------------------------------------------------------------------------
262 // ----------------------------------------------------------------------------
263 IMPLEMENT_APP(RegApp
)
265 // `Main program' equivalent, creating windows and returning main app frame
266 bool RegApp::OnInit()
268 // create the main frame window and show it
269 RegFrame
*frame
= new RegFrame(NULL
, "wxRegKey Test", 50, 50, 600, 350);
277 // ----------------------------------------------------------------------------
279 // ----------------------------------------------------------------------------
281 RegFrame::RegFrame(wxFrame
*parent
, char *title
, int x
, int y
, int w
, int h
)
282 : wxFrame(parent
, -1, title
, wxPoint(x
, y
), wxSize(w
, h
))
284 // this reduces flicker effects
285 SetBackgroundColour(wxColour(255, 255, 255));
289 SetIcon(wxIcon("app_icon"));
293 wxMenu
*pMenuFile
= new wxMenu
;
294 pMenuFile
->Append(Menu_Test
, "Te&st", "Test key creation");
295 pMenuFile
->AppendSeparator();
296 pMenuFile
->Append(Menu_About
, "&About...", "Show an extraordinarly beautiful dialog");
297 pMenuFile
->AppendSeparator();
298 pMenuFile
->Append(Menu_Quit
, "E&xit", "Quit this program");
300 wxMenuBar
*pMenu
= new wxMenuBar
;
301 pMenu
->Append(pMenuFile
, "&File");
302 pMenu
->Append(CreateRegistryMenu(), "&Registry");
305 // create child controls
306 // ---------------------
307 m_treeCtrl
= new RegTreeCtrl(this, Ctrl_RegTree
);
309 // create the status line
310 // ----------------------
315 SetStatusWidths(2, aWidths
);
318 RegFrame::~RegFrame(void)
322 void RegFrame::OnQuit(wxCommandEvent
& event
)
327 void RegFrame::OnAbout(wxCommandEvent
& event
)
329 wxMessageDialog
dialog(this, "wxRegistry sample\n(c) 1998 Vadim Zeitlin",
330 "About wxRegistry", wxOK
);
335 void RegFrame::OnTest(wxCommandEvent
& event
)
337 m_treeCtrl
->OnMenuTest();
340 void RegFrame::OnExpand(wxCommandEvent
& event
)
342 m_treeCtrl
->ExpandItem(m_treeCtrl
->GetSelection(), wxTREE_EXPAND_EXPAND
);
345 void RegFrame::OnCollapse(wxCommandEvent
& event
)
347 m_treeCtrl
->ExpandItem(m_treeCtrl
->GetSelection(), wxTREE_EXPAND_COLLAPSE
);
350 void RegFrame::OnToggle(wxCommandEvent
& event
)
352 m_treeCtrl
->ExpandItem(m_treeCtrl
->GetSelection(), wxTREE_EXPAND_TOGGLE
);
355 void RegFrame::OnDelete(wxCommandEvent
& event
)
357 m_treeCtrl
->DeleteSelected();
360 void RegFrame::OnNewKey(wxCommandEvent
& event
)
362 if ( m_treeCtrl
->IsKeySelected() ) {
363 m_treeCtrl
->CreateNewKey(
364 wxGetTextFromUser("Enter the name of the new key"));
368 void RegFrame::OnNewText(wxCommandEvent
& event
)
370 if ( m_treeCtrl
->IsKeySelected() ) {
371 m_treeCtrl
->CreateNewTextValue(
372 wxGetTextFromUser("Enter the name for the new text value"));
376 void RegFrame::OnNewBinary(wxCommandEvent
& event
)
378 if ( m_treeCtrl
->IsKeySelected() ) {
379 m_treeCtrl
->CreateNewBinaryValue(
380 wxGetTextFromUser("Enter the name for the new binary value"));
384 // ----------------------------------------------------------------------------
386 // ----------------------------------------------------------------------------
387 RegImageList::RegImageList() : wxImageList(16, 16, TRUE
)
389 // should be in sync with enum RegImageList::RegIcon
390 static const char *aszIcons
[] = { "key1","key2","key3","value1","value2" };
391 wxString str
= "icon_";
392 for ( uint n
= 0; n
< WXSIZEOF(aszIcons
); n
++ ) {
393 Add(wxIcon(str
+ aszIcons
[n
], wxBITMAP_TYPE_ICO_RESOURCE
));
397 // ----------------------------------------------------------------------------
399 // ----------------------------------------------------------------------------
401 // create a new tree item and insert it into the tree
402 RegTreeCtrl::TreeNode
*RegTreeCtrl::InsertNewTreeNode(TreeNode
*pParent
,
403 const wxString
& strName
,
405 const wxString
*pstrValue
)
407 // create new item & insert it
408 TreeNode
*pNewNode
= new TreeNode
;
409 pNewNode
->m_pTree
= this;
410 pNewNode
->m_pParent
= pParent
;
411 pNewNode
->m_strName
= strName
;
412 pNewNode
->m_bKey
= pstrValue
== NULL
;
413 pNewNode
->m_pKey
= NULL
;
414 pNewNode
->m_id
= InsertItem(pParent
? pParent
->m_id
: 0,
415 pNewNode
->IsKey() ? strName
: *pstrValue
,
418 wxASSERT_MSG( pNewNode
->m_id
, "can't create tree control item!");
420 // save the pointer in the item
421 if ( !SetItemData(pNewNode
->m_id
, (long)pNewNode
) ) {
422 wxFAIL_MSG("can't store item's data in tree control!");
425 // add it to the list of parent's children
426 if ( pParent
!= NULL
) {
427 pParent
->m_aChildren
.Add(pNewNode
);
430 // force the [+] button (@@@ not very elegant...)
431 if ( pNewNode
->IsKey() )
432 pNewNode
->AddDummy();
437 RegTreeCtrl::RegTreeCtrl(wxWindow
*parent
, wxWindowID id
)
438 : wxTreeCtrl(parent
, id
, wxDefaultPosition
, wxDefaultSize
,
439 wxTR_HAS_BUTTONS
| wxSUNKEN_BORDER
)
441 // create the image list
442 // ---------------------
443 m_imageList
= new RegImageList
;
444 SetImageList(m_imageList
, wxIMAGE_LIST_NORMAL
);
448 m_pRoot
= InsertNewTreeNode(NULL
, "Registry Root", RegImageList::Root
);
452 m_pMenuPopup
= CreateRegistryMenu();
455 RegTreeCtrl::~RegTreeCtrl()
462 void RegTreeCtrl::AddStdKeys()
464 for ( uint ui
= 0; ui
< wxRegKey::nStdKeys
; ui
++ ) {
465 InsertNewTreeNode(m_pRoot
, wxRegKey::GetStdKeyName(ui
));
469 // ----------------------------------------------------------------------------
471 // ----------------------------------------------------------------------------
473 void RegTreeCtrl::OnRightClick(wxMouseEvent
& event
)
476 long lId
= HitTest(wxPoint(event
.GetX(), event
.GetY()), iFlags
);
477 if ( iFlags
& wxTREE_HITTEST_ONITEMLABEL
) {
478 // popup menu only if an item was clicked
479 wxASSERT( lId
!= 0 );
481 PopupMenu(m_pMenuPopup
, event
.GetX(), event
.GetY());
486 void RegTreeCtrl::OnDeleteItem(wxTreeEvent
& event
)
490 // test the key creation functions
491 void RegTreeCtrl::OnMenuTest()
493 long lId
= GetSelection();
494 TreeNode
*pNode
= (TreeNode
*)GetItemData(lId
);
496 wxCHECK_RET( pNode
!= NULL
, "tree item without data?" );
498 if ( pNode
->IsRoot() ) {
499 wxLogError("Can't create a subkey under the root key.");
502 if ( !pNode
->IsKey() ) {
503 wxLogError("Can't create a subkey under a value!");
507 wxRegKey
key1(pNode
->Key(), "key1");
508 if ( key1
.Create() ) {
509 wxRegKey
key2a(key1
, "key2a"), key2b(key1
, "key2b");
510 if ( key2a
.Create() && key2b
.Create() ) {
511 // put some values under the newly created keys
512 key1
.SetValue("first_term", "10");
513 key1
.SetValue("second_term", "7");
514 key2a
= "this is the unnamed value";
515 key2b
.SetValue("sum", 17);
519 wxLogStatus("Test keys successfully added.");
524 wxLogError("Creation of test keys failed.");
527 void RegTreeCtrl::OnChar(wxKeyEvent
& event
)
529 if ( event
.KeyCode() == WXK_DELETE
)
532 wxTreeCtrl::OnChar(event
);
535 void RegTreeCtrl::OnSelChanged(wxTreeEvent
& event
)
537 wxFrame
*pFrame
= (wxFrame
*)(wxWindow::GetParent());
538 pFrame
->SetStatusText(GetNode(event
)->FullName(), 1);
541 void RegTreeCtrl::OnItemExpanding(wxTreeEvent
& event
)
543 TreeNode
*pNode
= GetNode(event
);
544 bool bExpanding
= event
.m_code
== wxTREE_EXPAND_EXPAND
;
546 // expansion might take some time
547 wxSetCursor(*wxHOURGLASS_CURSOR
);
548 wxLogStatus("Working...");
549 wxYield(); // to give the status line a chance to refresh itself
551 if ( pNode
->IsKey() ) {
553 // expanding: add subkeys/values
554 if ( !pNode
->OnExpand() )
558 // collapsing: clean up
562 // change icon for non root key
563 if ( !pNode
->IsRoot() ) {
564 int idIcon
= bExpanding
? RegImageList::OpenedKey
565 : RegImageList::ClosedKey
;
566 SetItemImage(pNode
->Id(), idIcon
, idIcon
);
571 wxSetCursor(*wxSTANDARD_CURSOR
);
574 // ----------------------------------------------------------------------------
575 // TreeNode implementation
576 // ----------------------------------------------------------------------------
577 bool RegTreeCtrl::TreeNode::OnExpand()
580 if ( m_lDummy
!= 0 ) {
581 m_pTree
->DeleteItem(m_lDummy
);
585 // we've been already expanded
590 // we're the root key
591 m_pTree
->AddStdKeys();
595 if ( Parent()->IsRoot() ) {
596 // we're a standard key
597 m_pKey
= new wxRegKey(m_strName
);
600 // we're a normal key
601 m_pKey
= new wxRegKey(*(Parent()->m_pKey
), m_strName
);
604 if ( !m_pKey
->Open() ) {
605 wxLogError("The key '%s' can't be opened.", FullName());
609 // enumeration variables
614 // enumerate all subkeys
615 bCont
= m_pKey
->GetFirstKey(str
, l
);
617 m_pTree
->InsertNewTreeNode(this, str
, RegImageList::ClosedKey
);
618 bCont
= m_pKey
->GetNextKey(str
, l
);
621 // enumerate all values
622 bCont
= m_pKey
->GetFirstValue(str
, l
);
626 strItem
= "<default>";
631 // determine the appropriate icon
632 RegImageList::Icon icon
;
633 switch ( m_pKey
->GetValueType(str
) ) {
634 case wxRegKey::Type_String
:
635 case wxRegKey::Type_Expand_String
:
636 case wxRegKey::Type_Multi_String
:
639 icon
= RegImageList::TextValue
;
640 m_pKey
->QueryValue(str
, strValue
);
645 case wxRegKey::Type_None
:
646 // @@ handle the error...
647 icon
= RegImageList::BinaryValue
;
650 case wxRegKey::Type_Dword
:
654 m_pKey
->QueryValue(str
, &l
);
655 sprintf(szBuf
, "%lx", l
);
662 icon
= RegImageList::BinaryValue
;
665 m_pTree
->InsertNewTreeNode(this, str
, icon
, &strItem
);
666 bCont
= m_pKey
->GetNextValue(str
, l
);
672 void RegTreeCtrl::TreeNode::OnCollapse()
674 bool bHasChildren
= !m_aChildren
.IsEmpty();
685 void RegTreeCtrl::TreeNode::AddDummy()
687 // insert dummy item forcing appearance of [+] button
688 m_lDummy
= m_pTree
->InsertItem(Id(), "");
691 void RegTreeCtrl::TreeNode::DestroyChildren()
693 // destroy all children
694 uint nCount
= m_aChildren
.Count();
695 for ( uint n
= 0; n
< nCount
; n
++ ) {
696 long lId
= m_aChildren
[n
]->Id();
697 delete m_aChildren
[n
];
698 m_pTree
->DeleteItem(lId
);
704 RegTreeCtrl::TreeNode::~TreeNode()
711 const char *RegTreeCtrl::TreeNode::FullName() const
713 static wxString s_strName
;
716 return "Registry Root";
719 // our own registry key might not (yet) exist or we might be a value,
720 // so just use the parent's and concatenate
721 s_strName
= Parent()->FullName();
722 s_strName
<< '\\' << m_strName
;
728 // ----------------------------------------------------------------------------
729 // operations on RegTreeCtrl
730 // ----------------------------------------------------------------------------
732 void RegTreeCtrl::DeleteSelected()
734 long lCurrent
= GetSelection(),
735 lParent
= GetParent(lCurrent
);
737 if ( lParent
== 0 ) {
738 wxLogError("Can't delete root key.");
742 TreeNode
*pCurrent
= (TreeNode
*)GetItemData(lCurrent
),
743 *pParent
= (TreeNode
*)GetItemData(lParent
);
745 wxCHECK_RET( pCurrent
&& pParent
, "either node or parent without data?" );
747 if ( pParent
->IsRoot() ) {
748 wxLogError("Can't delete standard key.");
752 if ( pCurrent
->IsKey() ) {
753 if ( wxMessageBox("Do you really want to delete this key?",
755 wxICON_QUESTION
| wxYES_NO
| wxCANCEL
, this) != wxYES
) {
759 // must close key before deleting it
760 pCurrent
->OnCollapse();
762 if ( pParent
->Key().DeleteKey(pCurrent
->m_strName
) )
766 if ( wxMessageBox("Do you really want to delete this value?",
768 wxICON_QUESTION
| wxYES_NO
| wxCANCEL
, this) != wxYES
) {
772 if ( pParent
->Key().DeleteValue(pCurrent
->m_strName
) )
777 void RegTreeCtrl::CreateNewKey(const wxString
& strName
)
779 long lCurrent
= GetSelection();
780 TreeNode
*pCurrent
= (TreeNode
*)GetItemData(lCurrent
);
782 wxCHECK_RET( pCurrent
!= NULL
, "node without data?" );
784 wxASSERT( pCurrent
->IsKey() ); // check must have been done before
786 if ( pCurrent
->IsRoot() ) {
787 wxLogError("Can't create a new key under the root key.");
791 wxRegKey
key(pCurrent
->Key(), strName
);
796 void RegTreeCtrl::CreateNewTextValue(const wxString
& strName
)
798 long lCurrent
= GetSelection();
799 TreeNode
*pCurrent
= (TreeNode
*)GetItemData(lCurrent
);
801 wxCHECK_RET( pCurrent
!= NULL
, "node without data?" );
803 wxASSERT( pCurrent
->IsKey() ); // check must have been done before
805 if ( pCurrent
->IsRoot() ) {
806 wxLogError("Can't create a new value under the root key.");
810 if ( pCurrent
->Key().SetValue(strName
, "") )
814 void RegTreeCtrl::CreateNewBinaryValue(const wxString
& strName
)
816 long lCurrent
= GetSelection();
817 TreeNode
*pCurrent
= (TreeNode
*)GetItemData(lCurrent
);
819 wxCHECK_RET( pCurrent
!= NULL
, "node without data?" );
821 wxASSERT( pCurrent
->IsKey() ); // check must have been done before
823 if ( pCurrent
->IsRoot() ) {
824 wxLogError("Can't create a new value under the root key.");
828 if ( pCurrent
->Key().SetValue(strName
, 0) )
832 bool RegTreeCtrl::IsKeySelected() const
834 long lCurrent
= GetSelection();
835 TreeNode
*pCurrent
= (TreeNode
*)GetItemData(lCurrent
);
837 wxCHECK( pCurrent
!= NULL
, false );
839 return pCurrent
->IsKey();