childwnd.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601
  1. /*
  2. * Regedit child window
  3. *
  4. * Copyright (C) 2002 Robert Dickenson <robd@reactos.org>
  5. *
  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.
  10. *
  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.
  15. *
  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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  19. */
  20. #define WIN32_LEAN_AND_MEAN /* Exclude rarely-used stuff from Windows headers */
  21. #include <windows.h>
  22. #include <commctrl.h>
  23. #include "main.h"
  24. #include "wine/debug.h"
  25. #include "wine/heap.h"
  26. WINE_DEFAULT_DEBUG_CHANNEL(regedit);
  27. ChildWnd* g_pChildWnd;
  28. static int last_split;
  29. static const WCHAR wszLastKey[] = {'L','a','s','t','K','e','y',0};
  30. static const WCHAR wszKeyName[] = {'S','o','f','t','w','a','r','e','\\',
  31. 'M','i','c','r','o','s','o','f','t','\\',
  32. 'W','i','n','d','o','w','s','\\',
  33. 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
  34. 'A','p','p','l','e','t','s','\\','R','e','g','e','d','i','t',0};
  35. /*******************************************************************************
  36. * Local module support methods
  37. */
  38. static LPCWSTR GetRootKeyName(HKEY hRootKey)
  39. {
  40. if(hRootKey == HKEY_CLASSES_ROOT)
  41. return reg_class_namesW[INDEX_HKEY_CLASSES_ROOT];
  42. if(hRootKey == HKEY_CURRENT_USER)
  43. return reg_class_namesW[INDEX_HKEY_CURRENT_USER];
  44. if(hRootKey == HKEY_LOCAL_MACHINE)
  45. return reg_class_namesW[INDEX_HKEY_LOCAL_MACHINE];
  46. if(hRootKey == HKEY_USERS)
  47. return reg_class_namesW[INDEX_HKEY_USERS];
  48. if(hRootKey == HKEY_CURRENT_CONFIG)
  49. return reg_class_namesW[INDEX_HKEY_CURRENT_CONFIG];
  50. if(hRootKey == HKEY_DYN_DATA)
  51. return reg_class_namesW[INDEX_HKEY_DYN_DATA];
  52. else
  53. {
  54. static const WCHAR unknown_key[] = {'U','N','K','N','O','W','N',' ','H','K','E','Y',',',' ',
  55. 'P','L','E','A','S','E',' ','R','E','P','O','R','T',0};
  56. return unknown_key;
  57. }
  58. }
  59. static void draw_splitbar(HWND hWnd, int x)
  60. {
  61. RECT rt;
  62. HDC hdc = GetDC(hWnd);
  63. GetClientRect(hWnd, &rt);
  64. rt.left = x - SPLIT_WIDTH/2;
  65. rt.right = x + SPLIT_WIDTH/2+1;
  66. InvertRect(hdc, &rt);
  67. ReleaseDC(hWnd, hdc);
  68. }
  69. static void ResizeWnd(int cx, int cy)
  70. {
  71. HDWP hdwp = BeginDeferWindowPos(2);
  72. RECT rt = {0, 0, cx, cy};
  73. cx = g_pChildWnd->nSplitPos + SPLIT_WIDTH/2;
  74. DeferWindowPos(hdwp, g_pChildWnd->hTreeWnd, 0, rt.left, rt.top, g_pChildWnd->nSplitPos-SPLIT_WIDTH/2-rt.left, rt.bottom-rt.top, SWP_NOZORDER|SWP_NOACTIVATE);
  75. DeferWindowPos(hdwp, g_pChildWnd->hListWnd, 0, rt.left+cx , rt.top, rt.right-cx, rt.bottom-rt.top, SWP_NOZORDER|SWP_NOACTIVATE);
  76. EndDeferWindowPos(hdwp);
  77. }
  78. static void OnPaint(HWND hWnd)
  79. {
  80. PAINTSTRUCT ps;
  81. RECT rt;
  82. GetClientRect(hWnd, &rt);
  83. BeginPaint(hWnd, &ps);
  84. FillRect(ps.hdc, &rt, GetSysColorBrush(COLOR_BTNFACE));
  85. EndPaint(hWnd, &ps);
  86. }
  87. static LPWSTR CombinePaths(LPCWSTR pPaths[], int nPaths) {
  88. int i, len, pos;
  89. LPWSTR combined;
  90. for (i=0, len=0; i<nPaths; i++) {
  91. if (pPaths[i] && *pPaths[i]) {
  92. len += lstrlenW(pPaths[i])+1;
  93. }
  94. }
  95. combined = heap_xalloc(len * sizeof(WCHAR));
  96. *combined = '\0';
  97. for (i=0, pos=0; i<nPaths; i++) {
  98. if (pPaths[i] && *pPaths[i]) {
  99. int llen = lstrlenW(pPaths[i]);
  100. if (!*combined)
  101. lstrcpyW(combined, pPaths[i]);
  102. else {
  103. combined[pos++] = '\\';
  104. lstrcpyW(combined+pos, pPaths[i]);
  105. }
  106. pos += llen;
  107. }
  108. }
  109. return combined;
  110. }
  111. static LPWSTR GetPathRoot(HWND hwndTV, HTREEITEM hItem, BOOL bFull) {
  112. LPCWSTR parts[2] = {0,0};
  113. WCHAR text[260];
  114. HKEY hRootKey = NULL;
  115. if (!hItem)
  116. hItem = (HTREEITEM)SendMessageW(hwndTV, TVM_GETNEXTITEM, TVGN_CARET, 0);
  117. heap_free(GetItemPath(hwndTV, hItem, &hRootKey));
  118. if (!bFull && !hRootKey)
  119. return NULL;
  120. if (hRootKey)
  121. parts[1] = GetRootKeyName(hRootKey);
  122. if (bFull) {
  123. DWORD dwSize = ARRAY_SIZE(text);
  124. GetComputerNameW(text, &dwSize);
  125. parts[0] = text;
  126. }
  127. return CombinePaths(parts, 2);
  128. }
  129. LPWSTR GetItemFullPath(HWND hwndTV, HTREEITEM hItem, BOOL bFull) {
  130. LPWSTR parts[2];
  131. LPWSTR ret;
  132. HKEY hRootKey = NULL;
  133. parts[0] = GetPathRoot(hwndTV, hItem, bFull);
  134. parts[1] = GetItemPath(hwndTV, hItem, &hRootKey);
  135. ret = CombinePaths((LPCWSTR *)parts, 2);
  136. heap_free(parts[0]);
  137. heap_free(parts[1]);
  138. return ret;
  139. }
  140. static void OnTreeSelectionChanged(HWND hwndTV, HWND hwndLV, HTREEITEM hItem, BOOL bRefreshLV)
  141. {
  142. if (bRefreshLV) {
  143. LPWSTR keyPath;
  144. HKEY hRootKey = NULL;
  145. HTREEITEM rootitem;
  146. rootitem = (HTREEITEM)SendMessageW(hwndTV, TVM_GETNEXTITEM, TVGN_ROOT, 0);
  147. if (rootitem == hItem)
  148. {
  149. SendMessageW(hwndLV, LVM_DELETEALLITEMS, 0, 0);
  150. UpdateStatusBar();
  151. return;
  152. }
  153. keyPath = GetItemPath(hwndTV, hItem, &hRootKey);
  154. RefreshListView(hwndLV, hRootKey, keyPath, NULL);
  155. heap_free(keyPath);
  156. }
  157. UpdateStatusBar();
  158. }
  159. /*******************************************************************************
  160. * finish_splitbar [internal]
  161. *
  162. * make the splitbar invisible and resize the windows
  163. * (helper for ChildWndProc)
  164. */
  165. static void finish_splitbar(HWND hWnd, int x)
  166. {
  167. RECT rt;
  168. draw_splitbar(hWnd, last_split);
  169. last_split = -1;
  170. GetClientRect(hWnd, &rt);
  171. g_pChildWnd->nSplitPos = x;
  172. ResizeWnd(rt.right, rt.bottom);
  173. ReleaseCapture();
  174. }
  175. /*******************************************************************************
  176. *
  177. * FUNCTION: _CmdWndProc(HWND, unsigned, WORD, LONG)
  178. *
  179. * PURPOSE: Processes WM_COMMAND messages for the main frame window.
  180. *
  181. */
  182. static BOOL _CmdWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
  183. {
  184. switch (LOWORD(wParam)) {
  185. /* Parse the menu selections: */
  186. case ID_REGISTRY_EXIT:
  187. DestroyWindow(hWnd);
  188. break;
  189. case ID_VIEW_REFRESH:
  190. WINE_TRACE("Is this ever called or is it just dead code?\n");
  191. /* TODO */
  192. break;
  193. case ID_SWITCH_PANELS:
  194. g_pChildWnd->nFocusPanel = !g_pChildWnd->nFocusPanel;
  195. SetFocus(g_pChildWnd->nFocusPanel? g_pChildWnd->hListWnd: g_pChildWnd->hTreeWnd);
  196. break;
  197. default:
  198. return FALSE;
  199. }
  200. return TRUE;
  201. }
  202. /*******************************************************************************
  203. * get_last_key [internal]
  204. *
  205. * open last key
  206. *
  207. */
  208. static void get_last_key(HWND hwndTV)
  209. {
  210. HKEY hkey;
  211. WCHAR wszVal[KEY_MAX_LEN];
  212. DWORD dwSize = sizeof(wszVal);
  213. if (RegCreateKeyExW(HKEY_CURRENT_USER, wszKeyName, 0, NULL, 0, KEY_READ, NULL, &hkey, NULL) == ERROR_SUCCESS)
  214. {
  215. HTREEITEM selection = NULL;
  216. if (RegQueryValueExW(hkey, wszLastKey, NULL, NULL, (LPBYTE)wszVal, &dwSize) == ERROR_SUCCESS)
  217. {
  218. if (lstrcmpW(wszVal, g_pChildWnd->szPath))
  219. selection = FindPathInTree(hwndTV, wszVal);
  220. }
  221. if(!selection)
  222. {
  223. selection = (HTREEITEM)SendMessageW(g_pChildWnd->hTreeWnd, TVM_GETNEXTITEM, TVGN_ROOT, 0);
  224. SendMessageW(hwndTV, TVM_EXPAND, TVE_EXPAND, (LPARAM)selection );
  225. }
  226. else
  227. SendMessageW(hwndTV, TVM_SELECTITEM, TVGN_CARET, (LPARAM)selection);
  228. RegCloseKey(hkey);
  229. }
  230. }
  231. /*******************************************************************************
  232. * set_last_key [internal]
  233. *
  234. * save last key
  235. *
  236. */
  237. static void set_last_key(HWND hwndTV)
  238. {
  239. HKEY hkey;
  240. if (RegCreateKeyExW(HKEY_CURRENT_USER, wszKeyName, 0, NULL, 0, KEY_WRITE, NULL, &hkey, NULL) == ERROR_SUCCESS)
  241. {
  242. HTREEITEM selection = (HTREEITEM)SendMessageW(g_pChildWnd->hTreeWnd, TVM_GETNEXTITEM, TVGN_CARET, 0);
  243. HTREEITEM root = (HTREEITEM)SendMessageW(g_pChildWnd->hTreeWnd, TVM_GETNEXTITEM, TVGN_ROOT, 0);
  244. WCHAR *value;
  245. if (selection == root)
  246. value = g_pChildWnd->szPath;
  247. else
  248. value = GetItemFullPath(g_pChildWnd->hTreeWnd, selection, FALSE);
  249. RegSetValueExW(hkey, wszLastKey, 0, REG_SZ, (LPBYTE)value, (lstrlenW(value) + 1) * sizeof(WCHAR));
  250. if (selection != root)
  251. heap_free(value);
  252. RegCloseKey(hkey);
  253. }
  254. }
  255. static int treeview_notify(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
  256. {
  257. switch (((NMHDR *)lParam)->code)
  258. {
  259. case NM_SETFOCUS:
  260. g_pChildWnd->nFocusPanel = 0;
  261. break;
  262. case TVN_BEGINLABELEDITW:
  263. {
  264. HKEY hRootKey;
  265. WCHAR *path;
  266. if (!GetWindowLongPtrW(g_pChildWnd->hTreeWnd, GWLP_USERDATA))
  267. return 1;
  268. path = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hRootKey);
  269. if (!path || !*path)
  270. return 1;
  271. return 0;
  272. }
  273. case TVN_ENDLABELEDITW:
  274. {
  275. HKEY hRootKey;
  276. NMTVDISPINFOW *dispInfo = (NMTVDISPINFOW *)lParam;
  277. WCHAR *path = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hRootKey);
  278. BOOL res = RenameKey(hWnd, hRootKey, path, dispInfo->item.pszText);
  279. heap_free(path);
  280. if (res)
  281. {
  282. TVITEMW item;
  283. item.mask = TVIF_HANDLE | TVIF_TEXT;
  284. item.hItem = dispInfo->item.hItem;
  285. item.pszText = dispInfo->item.pszText;
  286. SendMessageW(g_pChildWnd->hTreeWnd, TVM_SETITEMW, 0, (LPARAM)&item);
  287. path = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hRootKey);
  288. update_listview_path(path);
  289. heap_free(path);
  290. UpdateStatusBar();
  291. }
  292. SetWindowLongPtrW(g_pChildWnd->hTreeWnd, GWLP_USERDATA, 0);
  293. return res;
  294. }
  295. case TVN_ITEMEXPANDINGW:
  296. return !OnTreeExpanding(g_pChildWnd->hTreeWnd, (NMTREEVIEWW *)lParam);
  297. case TVN_SELCHANGEDW:
  298. OnTreeSelectionChanged(g_pChildWnd->hTreeWnd, g_pChildWnd->hListWnd,
  299. ((NMTREEVIEWW *)lParam)->itemNew.hItem, TRUE);
  300. break;
  301. }
  302. return 0;
  303. }
  304. static int listview_notify(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
  305. {
  306. switch (((NMHDR *)lParam)->code)
  307. {
  308. case NM_DBLCLK:
  309. {
  310. NMITEMACTIVATE *nmitem = (NMITEMACTIVATE *)lParam;
  311. if (nmitem->iItem != -1)
  312. {
  313. LVITEMW item;
  314. item.state = 0;
  315. item.stateMask = LVIS_FOCUSED | LVIS_SELECTED;
  316. SendMessageW(g_pChildWnd->hListWnd, LVM_SETITEMSTATE, (UINT)-1, (LPARAM)&item);
  317. item.state = LVIS_FOCUSED | LVIS_SELECTED;
  318. item.stateMask = LVIS_FOCUSED | LVIS_SELECTED;
  319. SendMessageW(g_pChildWnd->hListWnd, LVM_SETITEMSTATE, nmitem->iItem, (LPARAM)&item);
  320. SendMessageW(hFrameWnd, WM_COMMAND, ID_EDIT_MODIFY, 0);
  321. }
  322. break;
  323. }
  324. case NM_RETURN:
  325. {
  326. int cnt = SendMessageW(g_pChildWnd->hListWnd, LVM_GETNEXTITEM, -1,
  327. MAKELPARAM(LVNI_FOCUSED | LVNI_SELECTED, 0));
  328. if (cnt != -1)
  329. SendMessageW(hFrameWnd, WM_COMMAND, ID_EDIT_MODIFY, 0);
  330. break;
  331. }
  332. case NM_SETFOCUS:
  333. g_pChildWnd->nFocusPanel = 1;
  334. break;
  335. case LVN_BEGINLABELEDITW:
  336. if (!((NMLVDISPINFOW *)lParam)->item.iItem)
  337. return 1;
  338. return 0;
  339. case LVN_COLUMNCLICK:
  340. if (g_columnToSort == ((NMLISTVIEW *)lParam)->iSubItem)
  341. g_invertSort = !g_invertSort;
  342. else
  343. {
  344. g_columnToSort = ((NMLISTVIEW *)lParam)->iSubItem;
  345. g_invertSort = FALSE;
  346. }
  347. SendMessageW(g_pChildWnd->hListWnd, LVM_SORTITEMS,
  348. (WPARAM)g_pChildWnd->hListWnd, (LPARAM)CompareFunc);
  349. break;
  350. case LVN_DELETEITEM:
  351. {
  352. NMLISTVIEW *nmlv = (NMLISTVIEW *)lParam;
  353. LINE_INFO *info = (LINE_INFO *)nmlv->lParam;
  354. heap_free(info->name);
  355. heap_free(info->val);
  356. heap_free(info);
  357. break;
  358. }
  359. case LVN_ENDLABELEDITW:
  360. {
  361. NMLVDISPINFOW *dispInfo = (NMLVDISPINFOW *)lParam;
  362. WCHAR *oldName = GetItemText(g_pChildWnd->hListWnd, dispInfo->item.iItem);
  363. LONG ret;
  364. if (!oldName) return -1; /* cannot rename a default value */
  365. ret = RenameValue(g_pChildWnd->hListWnd, g_currentRootKey, g_currentPath,
  366. oldName, dispInfo->item.pszText);
  367. if (ret)
  368. {
  369. dispInfo->item.iSubItem = 0;
  370. SendMessageW(g_pChildWnd->hListWnd, LVM_SETITEMTEXTW,
  371. dispInfo->item.iItem, (LPARAM)&dispInfo->item);
  372. }
  373. heap_free(oldName);
  374. return 0;
  375. }
  376. case LVN_GETDISPINFOW:
  377. OnGetDispInfo((NMLVDISPINFOW *)lParam);
  378. break;
  379. }
  380. return 0;
  381. }
  382. #define GET_X_LPARAM(lp) ((int)(short)LOWORD(lp))
  383. #define GET_Y_LPARAM(lp) ((int)(short)HIWORD(lp))
  384. /*******************************************************************************
  385. *
  386. * FUNCTION: ChildWndProc(HWND, unsigned, WORD, LONG)
  387. *
  388. * PURPOSE: Processes messages for the child windows.
  389. *
  390. * WM_COMMAND - process the application menu
  391. * WM_PAINT - Paint the main window
  392. * WM_DESTROY - post a quit message and return
  393. *
  394. */
  395. LRESULT CALLBACK ChildWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
  396. {
  397. switch (message) {
  398. case WM_CREATE:
  399. g_pChildWnd = heap_xalloc(sizeof(ChildWnd));
  400. if (!g_pChildWnd) return 0;
  401. LoadStringW(hInst, IDS_REGISTRY_ROOT_NAME, g_pChildWnd->szPath, MAX_PATH);
  402. g_pChildWnd->nSplitPos = 250;
  403. g_pChildWnd->hWnd = hWnd;
  404. g_pChildWnd->hTreeWnd = CreateTreeView(hWnd, g_pChildWnd->szPath, TREE_WINDOW);
  405. g_pChildWnd->hListWnd = CreateListView(hWnd, LIST_WINDOW/*, g_pChildWnd->szPath*/);
  406. g_pChildWnd->nFocusPanel = 1;
  407. SetFocus(g_pChildWnd->hTreeWnd);
  408. get_last_key(g_pChildWnd->hTreeWnd);
  409. break;
  410. case WM_COMMAND:
  411. if (!_CmdWndProc(hWnd, message, wParam, lParam)) {
  412. goto def;
  413. }
  414. break;
  415. case WM_PAINT:
  416. OnPaint(hWnd);
  417. return 0;
  418. case WM_SETCURSOR:
  419. if (LOWORD(lParam) == HTCLIENT) {
  420. POINT pt;
  421. GetCursorPos(&pt);
  422. ScreenToClient(hWnd, &pt);
  423. if (pt.x>=g_pChildWnd->nSplitPos-SPLIT_WIDTH/2 && pt.x<g_pChildWnd->nSplitPos+SPLIT_WIDTH/2+1) {
  424. SetCursor(LoadCursorW(0, (LPCWSTR)IDC_SIZEWE));
  425. return TRUE;
  426. }
  427. }
  428. goto def;
  429. case WM_DESTROY:
  430. set_last_key(g_pChildWnd->hTreeWnd);
  431. heap_free(g_pChildWnd);
  432. g_pChildWnd = NULL;
  433. PostQuitMessage(0);
  434. break;
  435. case WM_LBUTTONDOWN: {
  436. RECT rt;
  437. int x = (short)LOWORD(lParam);
  438. GetClientRect(hWnd, &rt);
  439. if (x>=g_pChildWnd->nSplitPos-SPLIT_WIDTH/2 && x<g_pChildWnd->nSplitPos+SPLIT_WIDTH/2+1) {
  440. last_split = g_pChildWnd->nSplitPos;
  441. draw_splitbar(hWnd, last_split);
  442. SetCapture(hWnd);
  443. }
  444. break;
  445. }
  446. /* WM_RBUTTONDOWN sets the splitbar the same way as WM_LBUTTONUP */
  447. case WM_LBUTTONUP:
  448. case WM_RBUTTONDOWN:
  449. if (GetCapture() == hWnd) {
  450. finish_splitbar(hWnd, LOWORD(lParam));
  451. }
  452. break;
  453. case WM_CAPTURECHANGED:
  454. if (GetCapture()==hWnd && last_split>=0)
  455. draw_splitbar(hWnd, last_split);
  456. break;
  457. case WM_CONTEXTMENU:
  458. {
  459. POINT pt = {GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)};
  460. short int menu_id = -1;
  461. if ((HWND)wParam == g_pChildWnd->hTreeWnd)
  462. {
  463. TVHITTESTINFO ht;
  464. ht.pt = pt;
  465. ScreenToClient(g_pChildWnd->hTreeWnd, &ht.pt);
  466. if (SendMessageW(g_pChildWnd->hTreeWnd, TVM_HITTEST, 0, (LPARAM)&ht))
  467. {
  468. HTREEITEM root;
  469. SendMessageW(g_pChildWnd->hTreeWnd, TVM_SELECTITEM, TVGN_CARET, (LPARAM)ht.hItem);
  470. root = (HTREEITEM)SendMessageW(g_pChildWnd->hTreeWnd, TVM_GETNEXTITEM, TVGN_ROOT, 0);
  471. menu_id = (ht.hItem == root) ? PM_COMPUTER : PM_TREEVIEW;
  472. }
  473. }
  474. else
  475. {
  476. int sel = SendMessageW(g_pChildWnd->hListWnd, LVM_GETNEXTITEM, -1,
  477. MAKELPARAM(LVNI_SELECTED, 0));
  478. menu_id = (sel == -1) ? PM_NEW_VALUE : PM_MODIFY_VALUE;
  479. }
  480. TrackPopupMenu(GetSubMenu(hPopupMenus, menu_id), TPM_RIGHTBUTTON,
  481. pt.x, pt.y, 0, hFrameWnd, NULL);
  482. break;
  483. }
  484. case WM_KEYDOWN:
  485. if (wParam == VK_ESCAPE)
  486. if (GetCapture() == hWnd) {
  487. RECT rt;
  488. draw_splitbar(hWnd, last_split);
  489. GetClientRect(hWnd, &rt);
  490. ResizeWnd(rt.right, rt.bottom);
  491. last_split = -1;
  492. ReleaseCapture();
  493. SetCursor(LoadCursorW(0, (LPCWSTR)IDC_ARROW));
  494. }
  495. break;
  496. case WM_MOUSEMOVE:
  497. if (GetCapture() == hWnd) {
  498. RECT rt;
  499. int x = LOWORD(lParam);
  500. HDC hdc = GetDC(hWnd);
  501. GetClientRect(hWnd, &rt);
  502. rt.left = last_split-SPLIT_WIDTH/2;
  503. rt.right = last_split+SPLIT_WIDTH/2+1;
  504. InvertRect(hdc, &rt);
  505. last_split = x;
  506. rt.left = x-SPLIT_WIDTH/2;
  507. rt.right = x+SPLIT_WIDTH/2+1;
  508. InvertRect(hdc, &rt);
  509. ReleaseDC(hWnd, hdc);
  510. }
  511. break;
  512. case WM_SETFOCUS:
  513. if (g_pChildWnd != NULL) {
  514. SetFocus(g_pChildWnd->nFocusPanel? g_pChildWnd->hListWnd: g_pChildWnd->hTreeWnd);
  515. }
  516. break;
  517. case WM_TIMER:
  518. break;
  519. case WM_NOTIFY:
  520. if (wParam == TREE_WINDOW && g_pChildWnd)
  521. return treeview_notify(hWnd, message, wParam, lParam);
  522. else if (wParam == LIST_WINDOW && g_pChildWnd)
  523. return listview_notify(hWnd, message, wParam, lParam);
  524. break;
  525. case WM_SIZE:
  526. if (wParam != SIZE_MINIMIZED && g_pChildWnd != NULL) {
  527. ResizeWnd(LOWORD(lParam), HIWORD(lParam));
  528. }
  529. /* fall through */
  530. default: def:
  531. return DefWindowProcW(hWnd, message, wParam, lParam);
  532. }
  533. return 0;
  534. }