childwnd.c 11 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
/*
 * Regedit child window
 *
 * Copyright (C) 2002 Robert Dickenson <robd@reactos.org>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#define WIN32_LEAN_AND_MEAN     /* Exclude rarely-used stuff from Windows headers */
#include <windows.h>
#include <commctrl.h>
24 25
#include <tchar.h>
#include <stdio.h>
26 27 28

#include "main.h"

29 30 31 32 33
#include "wine/debug.h"
#include "wine/unicode.h"
                                                                                                                             
WINE_DEFAULT_DEBUG_CHANNEL(regedit);
                                                                                                                             
34
ChildWnd* g_pChildWnd;
35 36 37 38 39

/*******************************************************************************
 * Local module support methods
 */

40
LPCTSTR GetRootKeyName(HKEY hRootKey)
41
{
42 43 44 45 46
    if (hRootKey == HKEY_CLASSES_ROOT) return _T("HKEY_CLASSES_ROOT");
    if (hRootKey == HKEY_CURRENT_USER) return _T("HKEY_CURRENT_USER");
    if (hRootKey == HKEY_LOCAL_MACHINE) return _T("HKEY_LOCAL_MACHINE");
    if (hRootKey == HKEY_USERS) return _T("HKEY_USERS");
    if (hRootKey == HKEY_CURRENT_CONFIG) return _T("HKEY_CURRENT_CONFIG");
47
    if (hRootKey == HKEY_DYN_DATA) return _T("HKEY_DYN_DATA");
48
    return _T("UNKNOWN HKEY, PLEASE REPORT");
49 50 51 52
}

static void draw_splitbar(HWND hWnd, int x)
{
53 54
    RECT rt;
    HDC hdc = GetDC(hWnd);
55

56 57 58 59 60
    GetClientRect(hWnd, &rt);
    rt.left = x - SPLIT_WIDTH/2;
    rt.right = x + SPLIT_WIDTH/2+1;
    InvertRect(hdc, &rt);
    ReleaseDC(hWnd, hdc);
61 62 63 64
}

static void ResizeWnd(ChildWnd* pChildWnd, int cx, int cy)
{
65 66
    HDWP hdwp = BeginDeferWindowPos(2);
    RECT rt = {0, 0, cx, cy};
67

68
    cx = pChildWnd->nSplitPos + SPLIT_WIDTH/2;
69 70
    DeferWindowPos(hdwp, pChildWnd->hTreeWnd, 0, rt.left, rt.top, pChildWnd->nSplitPos-SPLIT_WIDTH/2-rt.left, rt.bottom-rt.top, SWP_NOZORDER|SWP_NOACTIVATE);
    DeferWindowPos(hdwp, pChildWnd->hListWnd, 0, rt.left+cx  , rt.top, rt.right-cx, rt.bottom-rt.top, SWP_NOZORDER|SWP_NOACTIVATE);
71
    EndDeferWindowPos(hdwp);
72 73 74 75 76 77 78 79 80 81
}

static void OnPaint(HWND hWnd)
{
    PAINTSTRUCT ps;
    RECT rt;
    HDC hdc;

    GetClientRect(hWnd, &rt);
    hdc = BeginPaint(hWnd, &ps);
82
    FillRect(ps.hdc, &rt, GetSysColorBrush(COLOR_BTNFACE));
83 84 85
    EndPaint(hWnd, &ps);
}

86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
static LPTSTR CombinePaths(LPCTSTR pPaths[], int nPaths) {
    int i, len, pos;
    LPTSTR combined;
    for (i=0, len=0; i<nPaths; i++) {
        if (pPaths[i] && *pPaths[i]) {
            len += lstrlen(pPaths[i])+1;
        }
    }
    combined = HeapAlloc(GetProcessHeap(), 0, len * sizeof(TCHAR));
    *combined = '\0';
    for (i=0, pos=0; i<nPaths; i++) {
        if (pPaths[i] && *pPaths[i]) {
            int llen = _tcslen(pPaths[i]);
            if (!*combined)
                _tcscpy(combined, pPaths[i]);
            else {
                combined[pos++] = (TCHAR)'\\';
                _tcscpy(combined+pos, pPaths[i]);
            }
            pos += llen;
106 107
        }
    }
108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138
    return combined;
}

LPTSTR GetItemFullPath(HWND hwndTV, HTREEITEM hItem, BOOL bFull) {
    LPCTSTR parts[3] = {_T(""), _T(""), _T("")};
    TCHAR text[260];
    HKEY hRootKey = NULL;
    if (!hItem)
        hItem = TreeView_GetSelection(hwndTV);
    parts[2] = GetItemPath(hwndTV, hItem, &hRootKey);
    if (!parts[2])
        parts[2] = _T("");
    if (!bFull && !hRootKey && !*parts[2])
        return NULL;
    if (hRootKey)
        parts[1] = GetRootKeyName(hRootKey);
    if (bFull) {
        DWORD dwSize = sizeof(text)/sizeof(TCHAR);
        GetComputerName(text, &dwSize);
        parts[0] = text;
    }
    return CombinePaths(parts, 3);
}

static void OnTreeSelectionChanged(HWND hwndTV, HWND hwndLV, HTREEITEM hItem, BOOL bRefreshLV)
{
    if (bRefreshLV) {
        LPCTSTR keyPath;
        HKEY hRootKey = NULL;
        keyPath = GetItemPath(hwndTV, hItem, &hRootKey);
        RefreshListView(hwndLV, hRootKey, keyPath, NULL);
139
    }
140
    UpdateStatusBar();
141 142
}

143 144 145 146 147 148 149 150 151 152
/*******************************************************************************
 *
 *  FUNCTION: _CmdWndProc(HWND, unsigned, WORD, LONG)
 *
 *  PURPOSE:  Processes WM_COMMAND messages for the main frame window.
 *
 */

static BOOL _CmdWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
153
    ChildWnd* pChildWnd = g_pChildWnd;
154 155
    switch (LOWORD(wParam)) {
        /* Parse the menu selections: */
156 157 158 159
    case ID_REGISTRY_EXIT:
        DestroyWindow(hWnd);
        break;
    case ID_VIEW_REFRESH:
Crestez Leonard's avatar
Crestez Leonard committed
160
        WINE_TRACE("Is this ever called or is it just dead code?\n");
161 162
        /* TODO */
        break;
163 164 165 166
    case ID_SWITCH_PANELS:
        pChildWnd->nFocusPanel = !pChildWnd->nFocusPanel;
        SetFocus(pChildWnd->nFocusPanel? pChildWnd->hListWnd: pChildWnd->hTreeWnd);
        break;
167 168 169
    default:
        return FALSE;
    }
170
    return TRUE;
171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186
}

/*******************************************************************************
 *
 *  FUNCTION: ChildWndProc(HWND, unsigned, WORD, LONG)
 *
 *  PURPOSE:  Processes messages for the child windows.
 *
 *  WM_COMMAND  - process the application menu
 *  WM_PAINT    - Paint the main window
 *  WM_DESTROY  - post a quit message and return
 *
 */
LRESULT CALLBACK ChildWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    static int last_split;
187
    ChildWnd* pChildWnd = g_pChildWnd;
188 189 190

    switch (message) {
    case WM_CREATE:
191
        g_pChildWnd = pChildWnd = HeapAlloc(GetProcessHeap(), 0, sizeof(ChildWnd));
192
        if (!pChildWnd) return 0;
193
        _tcsncpy(pChildWnd->szPath, _T("My Computer"), MAX_PATH);
194
        pChildWnd->nSplitPos = 250;
195
        pChildWnd->hWnd = hWnd;
196 197
        pChildWnd->hTreeWnd = CreateTreeView(hWnd, pChildWnd->szPath, TREE_WINDOW);
        pChildWnd->hListWnd = CreateListView(hWnd, LIST_WINDOW/*, pChildWnd->szPath*/);
198
        pChildWnd->nFocusPanel = 1;
199
        SetFocus(pChildWnd->hTreeWnd);
200 201 202 203 204
        break;
    case WM_COMMAND:
        if (!_CmdWndProc(hWnd, message, wParam, lParam)) {
            goto def;
        }
205
        break;
206 207 208
    case WM_PAINT:
        OnPaint(hWnd);
        return 0;
209 210 211 212 213 214 215 216 217 218 219
    case WM_SETCURSOR:
        if (LOWORD(lParam) == HTCLIENT) {
            POINT pt;
            GetCursorPos(&pt);
            ScreenToClient(hWnd, &pt);
            if (pt.x>=pChildWnd->nSplitPos-SPLIT_WIDTH/2 && pt.x<pChildWnd->nSplitPos+SPLIT_WIDTH/2+1) {
                SetCursor(LoadCursor(0, IDC_SIZEWE));
                return TRUE;
            }
        }
        goto def;
220
    case WM_DESTROY:
221 222
        HeapFree(GetProcessHeap(), 0, pChildWnd);
        pChildWnd = NULL;
223 224
        PostQuitMessage(0);
        break;
225 226 227 228 229 230 231 232 233 234 235
    case WM_LBUTTONDOWN: {
            RECT rt;
            int x = LOWORD(lParam);
            GetClientRect(hWnd, &rt);
            if (x>=pChildWnd->nSplitPos-SPLIT_WIDTH/2 && x<pChildWnd->nSplitPos+SPLIT_WIDTH/2+1) {
                last_split = pChildWnd->nSplitPos;
                draw_splitbar(hWnd, last_split);
                SetCapture(hWnd);
            }
            break;
        }
236

237 238 239 240 241 242 243 244 245 246 247 248
    case WM_LBUTTONUP:
        if (GetCapture() == hWnd) {
            RECT rt;
            int x = LOWORD(lParam);
            draw_splitbar(hWnd, last_split);
            last_split = -1;
            GetClientRect(hWnd, &rt);
            pChildWnd->nSplitPos = x;
            ResizeWnd(pChildWnd, rt.right, rt.bottom);
            ReleaseCapture();
        }
        break;
249

250 251 252 253
    case WM_CAPTURECHANGED:
        if (GetCapture()==hWnd && last_split>=0)
            draw_splitbar(hWnd, last_split);
        break;
254 255

    case WM_KEYDOWN:
256 257 258 259 260
        if (wParam == VK_ESCAPE)
            if (GetCapture() == hWnd) {
                RECT rt;
                draw_splitbar(hWnd, last_split);
                GetClientRect(hWnd, &rt);
261
                ResizeWnd(pChildWnd, rt.right, rt.bottom);
262 263 264 265 266
                last_split = -1;
                ReleaseCapture();
                SetCursor(LoadCursor(0, IDC_ARROW));
            }
        break;
267

268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283
    case WM_MOUSEMOVE:
        if (GetCapture() == hWnd) {
            RECT rt;
            int x = LOWORD(lParam);
            HDC hdc = GetDC(hWnd);
            GetClientRect(hWnd, &rt);
            rt.left = last_split-SPLIT_WIDTH/2;
            rt.right = last_split+SPLIT_WIDTH/2+1;
            InvertRect(hdc, &rt);
            last_split = x;
            rt.left = x-SPLIT_WIDTH/2;
            rt.right = x+SPLIT_WIDTH/2+1;
            InvertRect(hdc, &rt);
            ReleaseDC(hWnd, hdc);
        }
        break;
284

285
    case WM_SETFOCUS:
286
        if (pChildWnd != NULL) {
287
            SetFocus(pChildWnd->nFocusPanel? pChildWnd->hListWnd: pChildWnd->hTreeWnd);
288
        }
289
        break;
290 291 292 293

    case WM_TIMER:
        break;

294
    case WM_NOTIFY:
295 296 297 298
        if ((int)wParam == TREE_WINDOW) {
            switch (((LPNMHDR)lParam)->code) {
            case TVN_ITEMEXPANDING:
                return !OnTreeExpanding(pChildWnd->hTreeWnd, (NMTREEVIEW*)lParam);
299 300 301
            case TVN_SELCHANGED:
                OnTreeSelectionChanged(pChildWnd->hTreeWnd, pChildWnd->hListWnd,
                    ((NMTREEVIEW *)lParam)->itemNew.hItem, TRUE);
302
                break;
303
	    case NM_SETFOCUS:
304
		pChildWnd->nFocusPanel = 0;
305
		break;
306 307 308 309 310 311 312
            case NM_RCLICK: {
		POINT pt;
                GetCursorPos(&pt);
		TrackPopupMenu(GetSubMenu(hPopupMenus, PM_NEW),
			       TPM_RIGHTBUTTON, pt.x, pt.y, 0, hFrameWnd, NULL);
		break;
            }
313 314 315 316 317 318 319 320 321 322
	    case TVN_ENDLABELEDIT: {
		HKEY hRootKey;
	        LPNMTVDISPINFO dispInfo = (LPNMTVDISPINFO)lParam;
		LPCTSTR path = GetItemPath(pChildWnd->hTreeWnd, 0, &hRootKey);
	        BOOL res = RenameKey(hWnd, hRootKey, path, dispInfo->item.pszText);
		if (res) {
		    TVITEMEX item;
		    item.mask = TVIF_HANDLE | TVIF_TEXT;
		    item.hItem = TreeView_GetSelection(pChildWnd->hTreeWnd);
		    item.pszText = dispInfo->item.pszText;
323
                    SendMessage( pChildWnd->hTreeWnd, TVM_SETITEMW, 0, (LPARAM)&item );
324 325 326
		}
		return res;
	    }
327
            default:
328
                return 0; /* goto def; */
329 330
            }
        } else
331
            if ((int)wParam == LIST_WINDOW) {
332
		if (((LPNMHDR)lParam)->code == NM_SETFOCUS) {
333 334
		    pChildWnd->nFocusPanel = 1;
		} else if (!SendMessage(pChildWnd->hListWnd, WM_NOTIFY_REFLECT, wParam, lParam)) {
335 336
                    goto def;
                }
337 338 339
            }
        break;

340
    case WM_SIZE:
341
        if (wParam != SIZE_MINIMIZED && pChildWnd != NULL) {
342
            ResizeWnd(pChildWnd, LOWORD(lParam), HIWORD(lParam));
343 344
        }
        /* fall through */
345
default: def:
346
        return DefWindowProc(hWnd, message, wParam, lParam);
347 348
    }
    return 0;
349
}