fc8918fbfc0feaafb299c8a44b251b6485b87f3a
[reactos.git] / rosapps / regedit / childwnd.c
1 /*
2 * ReactOS regedit
3 *
4 * childwnd.c
5 *
6 * Copyright (C) 2002 Robert Dickenson <robd@reactos.org>
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 */
22
23 #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
24 #include <windows.h>
25 #include <commctrl.h>
26 #include <stdlib.h>
27 #include <malloc.h>
28 #include <memory.h>
29 #include <tchar.h>
30 #include <process.h>
31 #include <stdio.h>
32
33 #include <assert.h>
34 #define ASSERT assert
35
36 #include "main.h"
37 #include "framewnd.h"
38 #include "childwnd.h"
39 #include "treeview.h"
40 #include "listview.h"
41
42
43 ////////////////////////////////////////////////////////////////////////////////
44 // Local module support methods
45 //
46
47 static void MakeFullRegPath(HWND hwndTV, HTREEITEM hItem, LPTSTR keyPath, int* pPathLen, int max)
48 {
49 TVITEM item;
50 item.mask = TVIF_PARAM;
51 item.hItem = hItem;
52 if (TreeView_GetItem(hwndTV, &item)) {
53 if (item.hItem != TreeView_GetRoot(hwndTV)) {
54 // recurse
55 MakeFullRegPath(hwndTV, TreeView_GetParent(hwndTV, hItem), keyPath, pPathLen, max);
56 keyPath[*pPathLen] = _T('\\');
57 ++(*pPathLen);
58 }
59 item.mask = TVIF_TEXT;
60 item.hItem = hItem;
61 item.pszText = &keyPath[*pPathLen];
62 item.cchTextMax = max - *pPathLen;
63 if (TreeView_GetItem(hwndTV, &item)) {
64 *pPathLen += _tcslen(item.pszText);
65 }
66 }
67 }
68
69 static void draw_splitbar(HWND hWnd, int x)
70 {
71 RECT rt;
72 HDC hdc = GetDC(hWnd);
73
74 GetClientRect(hWnd, &rt);
75 rt.left = x - SPLIT_WIDTH/2;
76 rt.right = x + SPLIT_WIDTH/2+1;
77 InvertRect(hdc, &rt);
78 ReleaseDC(hWnd, hdc);
79 }
80
81 static void ResizeWnd(ChildWnd* pChildWnd, int cx, int cy)
82 {
83 HDWP hdwp = BeginDeferWindowPos(2);
84 RECT rt = {0, 0, cx, cy};
85
86 cx = pChildWnd->nSplitPos + SPLIT_WIDTH/2;
87 DeferWindowPos(hdwp, pChildWnd->hTreeWnd, 0, rt.left, rt.top, pChildWnd->nSplitPos-SPLIT_WIDTH/2-rt.left, rt.bottom-rt.top, SWP_NOZORDER|SWP_NOACTIVATE);
88 DeferWindowPos(hdwp, pChildWnd->hListWnd, 0, rt.left+cx , rt.top, rt.right-cx, rt.bottom-rt.top, SWP_NOZORDER|SWP_NOACTIVATE);
89 EndDeferWindowPos(hdwp);
90 }
91
92 static void OnPaint(HWND hWnd)
93 {
94 PAINTSTRUCT ps;
95 RECT rt;
96 HDC hdc;
97
98 GetClientRect(hWnd, &rt);
99 hdc = BeginPaint(hWnd, &ps);
100 FillRect(ps.hdc, &rt, GetStockObject(LTGRAY_BRUSH));
101 EndPaint(hWnd, &ps);
102 }
103
104 ////////////////////////////////////////////////////////////////////////////////
105 //
106 // FUNCTION: _CmdWndProc(HWND, unsigned, WORD, LONG)
107 //
108 // PURPOSE: Processes WM_COMMAND messages for the main frame window.
109 //
110 //
111
112 static BOOL _CmdWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
113 {
114 switch (LOWORD(wParam)) {
115 // Parse the menu selections:
116 case ID_REGISTRY_EXIT:
117 DestroyWindow(hWnd);
118 break;
119 case ID_VIEW_REFRESH:
120 // TODO:
121 break;
122 default:
123 return FALSE;
124 }
125 return TRUE;
126 }
127
128 ////////////////////////////////////////////////////////////////////////////////
129 //
130 // FUNCTION: ChildWndProc(HWND, unsigned, WORD, LONG)
131 //
132 // PURPOSE: Processes messages for the child windows.
133 //
134 // WM_COMMAND - process the application menu
135 // WM_PAINT - Paint the main window
136 // WM_DESTROY - post a quit message and return
137 //
138 //
139 LRESULT CALLBACK ChildWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
140 {
141 static int last_split;
142 // ChildWnd* pChildWnd = (ChildWnd*)GetWindowLong(hWnd, GWL_USERDATA);
143 static ChildWnd* pChildWnd;
144
145 switch (message) {
146 case WM_CREATE:
147 pChildWnd = (ChildWnd*)((LPCREATESTRUCT)lParam)->lpCreateParams;
148 ASSERT(pChildWnd);
149 pChildWnd->nSplitPos = 250;
150 pChildWnd->hTreeWnd = CreateTreeView(hWnd, pChildWnd->szPath, TREE_WINDOW);
151 pChildWnd->hListWnd = CreateListView(hWnd, LIST_WINDOW/*, pChildWnd->szPath*/);
152 break;
153 case WM_COMMAND:
154 if (!_CmdWndProc(hWnd, message, wParam, lParam)) {
155 goto def;
156 }
157 break;
158 case WM_PAINT:
159 OnPaint(hWnd);
160 return 0;
161 case WM_SETCURSOR:
162 if (LOWORD(lParam) == HTCLIENT) {
163 POINT pt;
164 GetCursorPos(&pt);
165 ScreenToClient(hWnd, &pt);
166 if (pt.x>=pChildWnd->nSplitPos-SPLIT_WIDTH/2 && pt.x<pChildWnd->nSplitPos+SPLIT_WIDTH/2+1) {
167 SetCursor(LoadCursor(0, IDC_SIZEWE));
168 return TRUE;
169 }
170 }
171 goto def;
172 case WM_DESTROY:
173 PostQuitMessage(0);
174 break;
175 case WM_LBUTTONDOWN: {
176 RECT rt;
177 int x = LOWORD(lParam);
178 GetClientRect(hWnd, &rt);
179 if (x>=pChildWnd->nSplitPos-SPLIT_WIDTH/2 && x<pChildWnd->nSplitPos+SPLIT_WIDTH/2+1) {
180 last_split = pChildWnd->nSplitPos;
181 draw_splitbar(hWnd, last_split);
182 SetCapture(hWnd);
183 }
184 break;}
185
186 case WM_LBUTTONUP:
187 if (GetCapture() == hWnd) {
188 RECT rt;
189 int x = LOWORD(lParam);
190 draw_splitbar(hWnd, last_split);
191 last_split = -1;
192 GetClientRect(hWnd, &rt);
193 pChildWnd->nSplitPos = x;
194 ResizeWnd(pChildWnd, rt.right, rt.bottom);
195 ReleaseCapture();
196 }
197 break;
198
199 case WM_CAPTURECHANGED:
200 if (GetCapture()==hWnd && last_split>=0)
201 draw_splitbar(hWnd, last_split);
202 break;
203
204 case WM_KEYDOWN:
205 if (wParam == VK_ESCAPE)
206 if (GetCapture() == hWnd) {
207 RECT rt;
208 draw_splitbar(hWnd, last_split);
209 GetClientRect(hWnd, &rt);
210 ResizeWnd(pChildWnd, rt.right, rt.bottom);
211 last_split = -1;
212 ReleaseCapture();
213 SetCursor(LoadCursor(0, IDC_ARROW));
214 }
215 break;
216
217 case WM_MOUSEMOVE:
218 if (GetCapture() == hWnd) {
219 RECT rt;
220 int x = LOWORD(lParam);
221 HDC hdc = GetDC(hWnd);
222 GetClientRect(hWnd, &rt);
223 rt.left = last_split-SPLIT_WIDTH/2;
224 rt.right = last_split+SPLIT_WIDTH/2+1;
225 InvertRect(hdc, &rt);
226 last_split = x;
227 rt.left = x-SPLIT_WIDTH/2;
228 rt.right = x+SPLIT_WIDTH/2+1;
229 InvertRect(hdc, &rt);
230 ReleaseDC(hWnd, hdc);
231 }
232 break;
233
234 case WM_SETFOCUS:
235 if (pChildWnd != NULL) {
236 SetFocus(pChildWnd->nFocusPanel? pChildWnd->hListWnd: pChildWnd->hTreeWnd);
237 }
238 break;
239
240 case WM_TIMER:
241 break;
242
243 case WM_NOTIFY:
244 if ((int)wParam == TREE_WINDOW) {
245 switch (((LPNMHDR)lParam)->code) {
246 case TVN_ITEMEXPANDING:
247 return !OnTreeExpanding(pChildWnd->hTreeWnd, (NMTREEVIEW*)lParam);
248 case TVN_SELCHANGED:
249 {
250 HKEY hKey;
251 TCHAR keyPath[1000];
252 int keyPathLen = 0;
253 keyPath[0] = _T('\0');
254 hKey = FindRegRoot(pChildWnd->hTreeWnd, ((NMTREEVIEW*)lParam)->itemNew.hItem, keyPath, &keyPathLen, sizeof(keyPath)/sizeof(TCHAR));
255 RefreshListView(pChildWnd->hListWnd, hKey, keyPath);
256
257 keyPathLen = 0;
258 keyPath[0] = _T('\0');
259 MakeFullRegPath(pChildWnd->hTreeWnd, ((NMTREEVIEW*)lParam)->itemNew.hItem, keyPath, &keyPathLen, sizeof(keyPath)/sizeof(TCHAR));
260 SendMessage(hStatusBar, SB_SETTEXT, 0, (LPARAM)keyPath);
261 }
262 break;
263 default:
264 goto def;
265 }
266 } else
267 if ((int)wParam == LIST_WINDOW) {
268 if (!SendMessage(pChildWnd->hListWnd, message, wParam, lParam)) {
269 goto def;
270 }
271 }
272 break;
273
274 case WM_SIZE:
275 if (wParam != SIZE_MINIMIZED && pChildWnd != NULL) {
276 ResizeWnd(pChildWnd, LOWORD(lParam), HIWORD(lParam));
277 }
278 // fall through
279 default: def:
280 return DefWindowProc(hWnd, message, wParam, lParam);
281 }
282 return 0;
283 }